處理日期和時間需要考慮很多事情,例如日期的格式、時區、閏年和天數各異的月份,自己處理太容易出錯了,我們應該使用PHP 5.2.0引入的DateTime、DateIntervel和DateTimeZone這些類幫助我們創建及處理日期、時間和時區。
設置默認時區:
首先我們要為PHP中處理日期和時間的函數設置默認時區,如果不設置的話,PHP會顯示一個E_WARNING消息,設置默認時區有兩種方式,可以像下面這樣在php.ini中設置:
date.timezone = 'Asia/Shanghai';
也可以在運行時使用date_default_timezone_set()函數設置:
date_default_timezone_set('Asia/Shanghai');
這兩種方式都要求使用有效的時區標識符,PHP完整的時區標識符可以在這里找到:http://php.net/manual/zh/timezones.php
DateTime類
DateTime類提供了一個面向對象接口,用于管理日期和時間,一個DateTime實例表示一個具體的日期和時間,DateTime構造方法是創建DateTime新實例最簡單的方式:
$datetime = new DateTime();
如果沒有參數,DateTime類的構造方法創建的是一個表示當前日期和時間的實例。我們可以把一個字符串傳入DateTime類的構造方法以便指定日期和時間:
$datetime = new DateTime('2016-06-06 10:00 pm');
注:傳入的字符串參數必須是有效的日期和時間格式(http://php.net/manual/zh/datetime.formats.php)
理想情況下,我們會指定PHP能理解的日期和時間格式,可是實際情況并不總是如此,有時我們必須處理其它格式或出乎意料的格式,這時我們可以通過DateTime提供的靜態方法createFromFormat來使用自定義的格式創建DateTime實例,該方法的第一個參數是表示日期和時間格式的字符串,第二個參數是要使用這種格式的日期和時間字符串:
$datetime = DateTime::createFromFormat('M j, Y H:i:s', 'June 6, 2016 22:00:00');
注:也許你很眼熟,沒錯,DateTime::createFromFormat和date函數類似??捎玫娜掌跁r間格式參考這里:http://php.net/manual/zh/datetime.createfromformat.php
DateInterval類
處理DateTime實例之前需要先了解DateInterval類,DateInterval實例表示長度固定的時間段(比如兩天),或者相對而言的時間段(例如昨天),我們通常使用該類的實例來修改DateTime實例。例如,DateTime提供了用于處理DateTime實例的add和sub方法,這兩個方法的參數是一個DateInterval實例,表示從DateTime中增加的時間量或減少的時間量。
我們使用構造函數實例化DateInterval實例,DateInterval構造函數的參數是一個表示時間間隔約定的字符串,這個時間間隔約定以字母P開頭,后面跟著一個整數,最后是一個周期標識符,限定前面的整數。有效周期標識符如下:
- Y(年)
- M(月)
- D(日)
- W(周)
- H(時)
- M(分)
- S(秒)
間隔約定中既可以有時間也可以有日期,如果有時間需要在日期和時間之間加上字母T,例如,間隔約定P2D表示間隔兩天,間隔約定P2DT5H2M表示間隔兩天五小時兩分鐘。
下面的實例演示了如何使用add方法將DateTime實例表示的日期和時間向后推移一段時間:
- //創建DateTime實例
- $datetime = new DateTime('2016-06-06 22:00:00');
- //創建長度為兩天的間隔
- $interval = new DateInterval('P2D');
- //修改DateTime實例
- $datetime->add($interval);
- echo $datetime->format('Y-m-d H:i:s');
我們還可以創建反向的DateInterval實例:
- $datetime = new DateTime();
- $interval = DateInterval::createFromDateString('-1 day');
- $period = new DatePeriod($datetime, $interval, 3);
- foreach ($period as $date) {
- echo $date->format('Y-m-d'), PHP_EOL;
- }
以上代碼輸出為:
- 2016-06-06
- 2016-06-05
- 2016-06-04
- 2016-06-03
DateTimeZone類
PHP使用DateTimeZone類表示時區,我們只需要把有效的時區標識符傳遞給DateTimeZone類的構造函數:
$timezone = new DateTimeZone('Asia/Shanghai');
創建DateTime實例通常需要使用DateTimeZone實例,DateTime類構造方法的第二個參數(可選)就是一個DateTimeZone實例,傳入這個參數后,DateTime實例的值以及對這個值的所有修改都相對于這個指定的時區,如果不傳入則使用的是前面設置的默認時區:
- $timezone = new DateTimeZone('Asia/Shanghai');
- $datetime = new DateTime('2016-06-06', $timezone);
實例化之后還可以使用setTimezone方法修改DateTime實例的時區:
- $timezone = new DateTimeZone('Asia/Shanghai');
- $datetime = new DateTime('2016-06-06', $timezone);
- $datetime->setTimezone(new DateTimeZone('Asia/Hong_kong'));
DatePeriod類
有時我們需要迭代處理一段時間內反復出現的一系列日期和時間,DatePeriod類可以解決這個問題(前面已經用到過),DatePeriod類的構造方法接受三個參數而且都必須提供:
一個DateTime實例,表示迭代開始的日期和時間
一個DateInterval實例,表示下一個日期和時間的間隔
一個整數,表示迭代的總次數
DatePeriod是迭代器,每次迭代都會產出一個DateTime實例。DatePeriod的第四個參數是可選的,用于顯式指定周期的結束日期和時間,如果迭代時想要排除開始日期和時間,可以把構造方法的最后一個參數設為DatePeriod::EXCLUDE_START_DATE常量:
- $datetime = new DateTime();
- $interval = new DateInterval('P2D');
- $period = new DatePeriod($datetime, $interval, 3, DatePeriod::EXCLUDE_START_DATE);
- foreach ($period as $date) {
- echo $date->format('Y-m-d H:i:s'), PHP_EOL;
- }
打印的結果是:
2016-06-08
2016-06-10
2016-06-12
nesbot/carbon日期組件
如果經常需要處理日期和時間,應該使用nesbot/carbon組件(https://github.com/briannesbitt/Carbon),Laravel框架也是使用了這個組件處理日期和時間,該組件集成了常用的日期及時間處理API,其底層正是使用了我們上面提到的幾個日期時間處理類實現了各種功能,有興趣可以去研究下。
新聞熱點
疑難解答