日期相干的操作函数是咱们在日常的工作开发中最常接触到的性能。当然,大部分同学可能最多用到的就是 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// 20200929var_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

参考文档:

https://www.php.net/manual/zh/book.datetime.php

各自媒体平台均可搜寻【硬核项目经理】