当前位置: 首页 > 后端技术 > PHP

PHP中日期相关的函数(一)

时间:2023-03-29 22:35:20 PHP

日期相关的操作函数是我们日常工作开发中最常遇到的函数。当然,大部分同学可能用得最多的是date()和time()这两个函数。这两个功能我们今天先不说,以后的文章可能也不太好讲,毕竟太常用了。在手册文档的学习中,我想发现一些有趣的或者没有接触过的功能,所以今天我们学习的功能可能不是每个人都用过,甚至很多人都没有见过。时区类的相关函数首先是时区类的一个对象。它可以帮助我们获取当前时区的一些信息。$timezone=newDateTimeZone('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)"北京时间"//}通过getLocation()可以获得时区的定位信息。经纬度查询结果为上海中心。评论区也明确指出当前时区为北京时间。//时区名称var_dump($timezone->getName());//string(13)"Asia/Shanghai"//相对于GMT的时差var_dump($timezone->getOffset(newDateTime('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()函数返回所有时区转换的时间。我测试的时间是早上。返回的时间字段内容为格林威治标准时间,offset字段也返回与GMT时间的差值。GMT时间与UTC时间一致。如果我们在日常学习和工作中接触到这两个名词,我们可以将它们视为同一个概念。UTC时间的标准名称是CoordinatedUniversalTime。以国际原子时为基础,世界各国的标准时间均以此为基础进行调整。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=newDateTime('2020-09-27');$beforeYestoday=newDateTime("2020-09-25");var_dump($today->diff($beforeYestoday));//对象(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=newDateInterval("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=newDateInterval("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)//}我们也可以通过日期数据以字段字符串的形式返回区间对象,例如://Createtimeintervalsfromdatestatementsvar_dump(DateInterval::createFromDateString('2days'));//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()方法,Date信息可以像printf()函数一样进行格式化,这里使用的格式化符仍然是日期格式化符var_dump($interval->format('%y%d%h%i'));//string(7)的输出其中的“2468”其实就是属性对应的日期时间差。时间段相关函数说完时间间隔,我们再来看看时间段。时间段是什么概念?比如我们要获取三天一次的日期,可以使用时间段相关的类进行处理。$start=newDateTime('2020-09-01');$interval=newDateInterval('P7D');$end=newDateTime('2020-09-30');$daterange=newDatePeriod($start,$interval,$end);var_dump($daterange);//对象(DatePeriod)#7(6){//["start"]=>//对象(DateTime)#8(3){//["date"]=>//string(26)"2020-09-0100:00:00.000000"//["timezone_type"]=>//int(3)//["timezone"]=>//string(13)"Asia/Shanghai"//}//["current"]=>//NULL//["end"]=>//object(DateTime)#9(3){//["date"]=>//string(26)"2020-09-3000: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($daterangeas$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-0100:00:00.000000"//["timezone_type"]=>//int(3)//["timezone"]=>//string(13)"亚洲/上海"//}var_dump($daterange->getEndDate());//对象ject(DateTime)#11(3){//["date"]=>//string(26)"2020-09-3000:00:00.000000"//["timezone_type"]=>//int(3)//["timezone"]=>//string(13)"Asia/Shanghai"//}它的方法实际上返回的是我们定义的构造参数信息。此外,它还可以指定起始点根据日期后的时间间隔返回几条信息。$period=newDatePeriod($start,$interval,4);foreach($periodas$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各媒体平台均可搜索【硬核项目经理】