首页 > php时间处理月份计算bug总结

php时间处理月份计算bug总结

2013-02-20   hisenKing

首先看下以下的代码,其中的结果并不是预期的2013-2-28

<?php
$date = '2013-01-31';
$nextMonth = strtotime('+1 month',strtotime($date));
$nextMonthDate = date("Y-m-d",$nextMonthDate);
// 结果返回2013-03-03

在来看下Linux 命令date,处理的月份计算的情况

$ date +"%Y-%m-%d" -d '2013-01-31 +1 month'
// 输出结果也是2013-03-03

看下sql的情况

mysql> SELECT DATE_ADD('2013-01-31', INTERVAL 1 MONTH);
        -> '2013-02-28

sql正确,php和linux命令都有问题。同时发现一个规律在处理月份的时间,原始日期指定这个月的某天超过结果月的天数时,会自动包含到下个月。 如:2013-03-31 加上一个月,结果则为2013-05-01。即2013-03-31加上一个月,得到2013-04-31,但是4月份并没有31号这一天,所以往下个月推一天,即得到2013-05-01;同理2013-01-31加一个月就得到了2013-03-03

php解决的办法: 1.在程序中避免月末的时候使用加减month操作 如统计数据的时候,程序放在月初执行或者时间换成月初, 2013-01-31,取前面的年月2013-01,代码补齐后面的日,时分秒2013-01 . '-01 00:00:00' 月末的使用date("Y-m-t")

2.代码中完善月份计算 其中zend框架的Zend_Date对月份的计算就进行了完善。

<?php
$zfdate = new Zend_Date('2013-01-31');
$zfdate->addMonth('1');
// 2013-2-28

$zfdate = new Zend_Date('2013-03-31');
$zfdate->addMonth('1');
// 2013-4-30

代码逻辑处理部分是Date.php

if (self::$_options['extend_month'] === false) {
      $parts = $this->getDateParts($this->mktime(
                   $hour, $minute, $second, $date, $day, $year, false));
      if ($parts['mday'] != $day) {
             $fixday = ($parts['mday'] < $day) 
                        ? -$parts['mday'] : ($parts['mday'] - $day);
      }
}

其中的$day为原始日期的day,$parts['mday']为结果月的day extend_month默认为false,处理月份的时间按sql方式兼容

好久没更新了,需要除除草