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