日期相關的操作函數是我們在日常的工作開發中最常接觸到的功能。當然,大部分同學可能最多用到的就是date()、time()這兩個函數,我們今天先不講這兩個函數,或許後面的文章也不太會講它們,畢竟太常用了。
本身在對手冊文件的學習中,就是要發掘有意思的或沒有接觸過的一些功能函數,所以我們今天的學習的函數可能是大家都沒怎麼用過的,甚至可能很多大家都沒見過的。
首先就是時區類別的物件。它可以幫助我們獲得一些當前時區相關的資訊。
$timezone = new DateTimeZone('Asia/Shanghai'); var_dump($timezone); // object(DateTimeZone)#1 (2) { // ["timezone_type"]=> // int(3) // ["timezone"]=> // string(13) "Asia/Shanghai" // }
在實例化這個 DateTimeZone 時區類別時,需要傳遞一個時區參數。這裡我們給的就是通用的中國時區的設置,雖說我們的國際標準時區是東八區的北京時間,但在 PHP 中的時區格式中,我們的時區是以上海為命名的。
這個時區類別可以直接獲得目前指定時區的定位訊息,例如 Asia/Shanghai 的定位資訊就是直接定位到上海市的。
// 时区相关的定位信息 var_dump($timezone->getLocation()); // array(4) { // ["country_code"]=> // string(2) "CN" // ["latitude"]=> // float(31.23333) // ["longitude"]=> // float(121.46666) // ["comments"]=> // string(12) "Beijing Time" // }
透過 getLocation() 就可以獲取到時區類的定位信息,經緯度的查詢結果就是上海市中心,comments 字段也明確地指出了當前時區是北京時間。
// 时区名称 var_dump($timezone->getName()); // string(13) "Asia/Shanghai" // 相对于 GMT 的时差 var_dump($timezone->getOffset(new DateTime('now', $timezone))); // int(28800) // 所有时区转换信息 var_dump($timezone->getTransitions(time())); // array(1) { // [0]=> // array(5) { // ["ts"]=> // int(1601168813) // ["time"]=> // string(24) "2020-09-27T01:06:53+0000" // ["offset"]=> // int(28800) // ["isdst"]=> // bool(false) // ["abbr"]=> // string(3) "CST" // } // }
getName() 方法取得的是目前時區的名稱,這個就不用多說了。 getOffset() 則是取得到與國際格林尼治時間(GMT)的差值,也就是與子午線的時間間隔,這裡回傳的是秒,轉換成小時後剛好就是 8 小時。
getTransitions() 函數傳回的是所有時區轉換的時間,我測試的時間是早上,傳回的 time 欄位內容是格林尼治時間,offset 欄位傳回的也是與GMT時間的差值。 GMT時間與UTC時間是一致的,我們在日常的學習和工作中如果接觸到了這兩個名詞可以將它們看做是相同的概念。
UTC時間的標準叫法是協調世界時間,基於國際原子時間,全世界的國家的標準時間都是以它為標準進行調校的,而GMT的本意是定位為本初子午線的平太陽時,UTC也是以這條經線為基準進行時區劃分的。不過,以嚴格的標準來說,它們並不是完全相等的,具體的內容大家可以自行查閱,但對於我們日常開發來說,完全可以將它們視為等同的東西。
// 包含 dst (夏令时),时差和时区信息的关联数组 var_dump(DateTimeZone::listAbbreviations()); // array(144) { // ["acdt"]=> // array(6) { // [0]=> // array(3) { // ["dst"]=> // bool(true) // ["offset"]=> // int(37800) // ["timezone_id"]=> // string(18) "Australia/Adelaide" // } // [1]=> // array(3) { // ["dst"]=> // bool(true) // ["offset"]=> // int(37800) // ["timezone_id"]=> // string(21) "Australia/Broken_Hill" // } // …… // …… // 包含了所有时区标示符的索引数组 var_dump(DateTimeZone::listIdentifiers()); // array(426) { // [0]=> // string(14) "Africa/Abidjan" // [1]=> // string(12) "Africa/Accra" // [2]=> // string(18) "Africa/Addis_Ababa" // [3]=> // string(14) "Africa/Algiers" // …… // ……
listAbbreviations() 靜態方法傳回的是 夏令時 相關的時差和時區資訊。夏令時 和 冬令時 也是西方國家的一種生活標準,我們接觸的不多,這裡就不做講解了,對於做跨境專案或歐美外包的同學應該不會陌生。 listIdentifiers() 方法傳回的是包含了所有時區標示符的索引數組,這裡可以看到所有的支援的時區資訊。
對時日期時間的間隔運算,或許大家多少都做過一點,例如 DateTime 物件的那個 diff() 方法。
$today = new DateTime('2020-09-27'); $beforeYestoday = new DateTime("2020-09-25"); var_dump($today->diff($beforeYestoday)); // object(DateInterval)#5 (16) { // ["y"]=> // int(0) // ["m"]=> // int(0) // ["d"]=> // int(2) // ["h"]=> // int(0) // ["i"]=> // int(0) // ["s"]=> // int(0) // ["f"]=> // float(0) // ["weekday"]=> // int(0) // ["weekday_behavior"]=> // int(0) // ["first_last_day_of"]=> // int(0) // ["invert"]=> // int(1) // ["days"]=> // int(2) // ["special_type"]=> // int(0) // ["special_amount"]=> // int(0) // ["have_weekday_relative"]=> // int(0) // ["have_special_relative"]=> // int(0) // }
從列印的結果可以看出,diff() 物件傳回的是一個 DateInterval 物件。這個就是我們這節的主角了,關於它印出來的這些屬性內容就不多解釋了,字段名已經非常直觀了,值就是具體的差值。
$interval = new DateInterval("P2D"); var_dump($interval); // object(DateInterval)#2 (16) { // ["y"]=> // int(0) // ["m"]=> // int(0) // ["d"]=> // int(2) // ["h"]=> // int(0) // ["i"]=> // int(0) // ["s"]=> // int(0) // ["f"]=> // float(0) // ["weekday"]=> // int(0) // ["weekday_behavior"]=> // int(0) // ["first_last_day_of"]=> // int(0) // ["invert"]=> // int(0) // ["days"]=> // bool(false) // ["special_type"]=> // int(0) // ["special_amount"]=> // int(0) // ["have_weekday_relative"]=> // int(0) // ["have_special_relative"]=> // int(0) // }
看到沒有?列印出來的內容和上面用 diff() 方法傳回的物件的內容是一致的,但是它的建構函數的參數很奇怪。沒錯,當我們自己去實例化一個 DateInterval 物件時,需要為它定義它的間隔訊息,這個間隔訊息就是我們透過建構函數的參數傳遞進去的。
P2D 的意思就是間隔2 天,首先必須以一個P 為開頭,然後可以有Y、M、D 這些日期內容,如果需要時間內容的話,需要一個T 然後再跟上H、M 、S 這些內容。例如 P2Y4DT6H8M 表示的就是 2年4天6小時8分鐘 的時間間隔。具體的規則大家還是去看文件中的說明:https://www.php.net/manual/zh/dateinterval.construct.php。
$interval = new DateInterval("P2Y4DT6H8M"); var_dump($interval); // object(DateInterval)#5 (16) { // ["y"]=> // int(2) // ["m"]=> // int(0) // ["d"]=> // int(4) // ["h"]=> // int(6) // ["i"]=> // int(8) // ["s"]=> // int(0) // ["f"]=> // float(0) // ["weekday"]=> // int(0) // ["weekday_behavior"]=> // int(0) // ["first_last_day_of"]=> // int(0) // ["invert"]=> // int(0) // ["days"]=> // bool(false) // ["special_type"]=> // int(0) // ["special_amount"]=> // int(0) // ["have_weekday_relative"]=> // int(0) // ["have_special_relative"]=> // int(0) // }
我們也可以透過欄位串形式的日期資料傳回間隔對象,例如:
// 从日期语句创建时间间隔 var_dump(DateInterval::createFromDateString('2 days')); // object(DateInterval)#3 (16) { // ["y"]=> // int(0) // ["m"]=> // int(0) // ["d"]=> // int(2) // ["h"]=> // int(0) // ["i"]=> // int(0) // ["s"]=> // int(0) // ["f"]=> // float(0) // ["weekday"]=> // int(0) // ["weekday_behavior"]=> // int(0) // ["first_last_day_of"]=> // int(0) // ["invert"]=> // int(0) // ["days"]=> // bool(false) // ["special_type"]=> // int(0) // ["special_amount"]=> // int(0) // ["have_weekday_relative"]=> // int(0) // ["have_special_relative"]=> // int(0) // }
此外,在取得物件後進行輸出的時候,DateInterval 物件也為我們提供了一個format () 方法,可以像printf() 函數一樣來格式化地輸出日期訊息,而且這裡用的格式符還是日期的格式符。
var_dump($interval->format('%y %d %h %i')); // string(7) "2 4 6 8"
輸出的內容其實就是屬性中對應的那些日期和時間差值。
說完時間間隔了,我們再來看看時間週期。時間週期是個什麼概念呢?就比如說我們要每三天間隔一次地取得日期,這時就可以用時間週期相關的類別來處理。
$start = new DateTime('2020-09-01'); $interval = new DateInterval('P7D'); $end = new DateTime('2020-09-30'); $daterange = new DatePeriod($start, $interval ,$end); var_dump($daterange); // object(DatePeriod)#7 (6) { // ["start"]=> // object(DateTime)#8 (3) { // ["date"]=> // string(26) "2020-09-01 00:00:00.000000" // ["timezone_type"]=> // int(3) // ["timezone"]=> // string(13) "Asia/Shanghai" // } // ["current"]=> // NULL // ["end"]=> // object(DateTime)#9 (3) { // ["date"]=> // string(26) "2020-09-30 00:00:00.000000" // ["timezone_type"]=> // int(3) // ["timezone"]=> // string(13) "Asia/Shanghai" // } // ["interval"]=> // object(DateInterval)#10 (16) { // ["y"]=> // int(0) // ["m"]=> // int(0) // ["d"]=> // int(7) // ["h"]=> // int(0) // ["i"]=> // int(0) // ["s"]=> // int(0) // ["f"]=> // float(0) // ["weekday"]=> // int(0) // ["weekday_behavior"]=> // int(0) // ["first_last_day_of"]=> // int(0) // ["invert"]=> // int(0) // ["days"]=> // bool(false) // ["special_type"]=> // int(0) // ["special_amount"]=> // int(0) // ["have_weekday_relative"]=> // int(0) // ["have_special_relative"]=> // int(0) // } // ["recurrences"]=> // int(1) // ["include_start_date"]=> // bool(true) // } foreach($daterange as $date){ echo $date->format("Ymd"), PHP_EOL; } // 20200901 // 20200908 // 20200915 // 20200922 // 20200929
首先设定了开始时间和结束时间以及一个时间间隔对象,然后用它们做为参数来生成一个 DatePeriod 时间周期对象。它是一个实现了迭代器的对象,所以我们可以直接遍历它,结果就是以 P7D ,也就是 7 天为间隔的一组日期数据。
var_dump($daterange->getDateInterval()); // object(DateInterval)#11 (16) { // ["y"]=> // int(0) // ["m"]=> // int(0) // ["d"]=> // int(7) // ["h"]=> // int(0) // ["i"]=> // int(0) // ["s"]=> // int(0) // ["f"]=> // float(0) // ["weekday"]=> // int(0) // ["weekday_behavior"]=> // int(0) // ["first_last_day_of"]=> // int(0) // ["invert"]=> // int(0) // ["days"]=> // bool(false) // ["special_type"]=> // int(0) // ["special_amount"]=> // int(0) // ["have_weekday_relative"]=> // int(0) // ["have_special_relative"]=> // int(0) // } var_dump($daterange->getStartDate()); // object(DateTime)#11 (3) { // ["date"]=> // string(26) "2020-09-01 00:00:00.000000" // ["timezone_type"]=> // int(3) // ["timezone"]=> // string(13) "Asia/Shanghai" // } var_dump($daterange->getEndDate()); // object(DateTime)#11 (3) { // ["date"]=> // string(26) "2020-09-30 00:00:00.000000" // ["timezone_type"]=> // int(3) // ["timezone"]=> // string(13) "Asia/Shanghai" // }
它的这一堆方法其实返回的就是我们定义的那些构造参数信息。另外,它还可以指定从开始日期往后按照时间间隔返回几条信息。
$period = new DatePeriod($start, $interval, 4); foreach($period as $date){ echo $date->format("Ymd"), PHP_EOL; } // 20200901 // 20200908 // 20200915 // 20200922 // 20200929 var_dump($period->getRecurrences()); // int(4)
recurrences 参数的作用就是按照指定的时间间隔返回几条信息,这里我们是返回 9月1号 之后每次间隔 7 天的 4 条信息,和上面的内容一样。这时我们修改构造函数的值为其它数量,比如修改为 2 ,那么就只会返回到 9月15号 的信息了。它不会受到结束日期的约束,可以返回从开始日期到指定数量之后的所有信息,大家可以自己尝试一下。
今天学习的内容不知道大家有没有接触过,反正我是只用过 diff() 方法来处理过日期之间的差值问题,而且也并没有注意到过它返回的这个对象具体的内容。
而另外两个对象则是压根没有印象,完全就是没听说过的感觉。所以说,平常多刷刷手册还是非常有帮助的,今天学习的内容又让我们知道了很多东西,而且 DatePeriod 在具体的业务实现中是肯定会有使用场景的。学习不止,后面我们要学习的内容依然精彩。
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202009/source/12.PHP中的日期相关函数(一).php
推荐学习:php视频教程
以上是PHP中與日期相關函數有哪些?的詳細內容。更多資訊請關注PHP中文網其他相關文章!