时间戳(年月日时分秒) 使用strtotime函数,结合+1 month,-1 month,next month,last month的时候会出现一些问题.
demo示例:
1 //时间"2018-10-16 12:00:00"增加一个月 2 $timeOne = strtotime("2018-10-16 12:00:00"); 3 echo date("Y-m-d H:i:s", strtotime("+ 1 month", $timeOne ));//2018-10-16 12:00:00[正确] 4 5 //时间"2018-10-31 10:00:00"增加一个月 6 $timeTwo = strtotime("2018-10-31 12:00:00"); 7 echo date("Y-m-d H:i:s", strtotime("+ 1 month", $timeTwo ));//2018-12-01 12:00:00[错误]
"date"内部逻辑的处理,其实是正确. 解析内部处理的逻辑?
1 (1): 先做+1 month,假设当前时间为10-31, 增加一个月时间为11-31 2 (2): 再做日期规范化,因为11月没有31日,所以就好像3点60等于4点一样;11月31日就等于12月1日
解决方法一: PHP>=5.3 date新增修正短语,用来明确这个问题,那就是"first day of" 和 "last day of",可以限定不要让date自动"规范化"
1 echo date("Y-m-d H:i:s", strtotime("last day of +1 month", strtotime("2018-10-31 12:00:00")));//2018-11-30 12:00:00[正确]
解决方法二: mktime 获取当前时间: date("Y-m-d H:i:s", mktime(date('H'),date('i') ,date('s'), date('m'), date('d'), date('Y')))
1 //设定时间"2018-10-31 12:00:00" 2 echo date("Y-m-d H:i:s", mktime(date('12'),0, 0, date('10'), date('31'), date('2018'))); 3 4 //指定增加30天,时间"2018-11-30 12:00:00" 5 echo date("Y-m-d H:i:s", mktime(date('12'),0, 0, date('10'), date('31')+30, date('2018')));//2018-11-30 12:00:00[正确]
解决方法三: (PHP 5 >= 5.2.0, PHP 7) DateTime
1 <?php 2 //设定初始时间: 'Y-m-d H:i:s' 3 $dateTime = new DateTime("2018-10-31 12:00:00"); 4 5 $addMonth = 1; //设定间隔的月份 6 7 //初始时间的天数值 8 $initDay = $dateTime->format("d"); 9 10 //DateInterval构造函数的参数是一个表示时间间隔约定的字符串,这个时间间隔约定以字母P开头,后面跟着一个整数,最后是一个周期标识符,限定前面的整数. 11 //有效周期标识符如下: Y(年) M(月) D(日) W(周) H(时) M(分) S(秒) 间隔约定中既可以有时间也可以有日期,如果有时间需要在日期和时间之间加上字母"T"用来分隔. 12 //例如: 间隔约定P2D表示间隔两天; 间隔约定P2DT5H2M表示间隔两天五小时两分钟 13 14 $dateTime->add(new DateInterval("P" . $addMonth . "M"));//增加 一个月时间; 2018-12-01 12:00:00[错误] 15 16 $newDay = $dateTime->format("d");//累加后新的日期的天数值 17 18 //判断间隔月份,天数值是否相同 19 if($initDay != $newDay) { 20 //不同减去差值 21 $dateTime->sub(new DateInterval("P" . $newDay . "D"));//减去 新初时间,天数差的值 22 } 23 24 echo $initDay;//31(天) 25 echo "<br>"; 26 echo $newDay;//1(天) 27 echo "<br>"; 28 echo $dateTime->format("Y-m-d H:i:s");//2018-11-30 12:00:00[正确]