这是PHP的DateTime:diff中的错误吗?

mpe*_*pen 4 php time datetime date date-math

>> $start_dt = new DateTime()
DateTime::__set_state(array(
   'date' => '2012-04-11 08:34:01',
   'timezone_type' => 3,
   'timezone' => 'America/Los_Angeles',
))
>> $end_dt = new DateTime()
DateTime::__set_state(array(
   'date' => '2012-04-11 08:34:06',
   'timezone_type' => 3,
   'timezone' => 'America/Los_Angeles',
))
>> $start_dt->setTimestamp(strtotime('31-Jan-2012'))
DateTime::__set_state(array(
   'date' => '2012-01-31 00:00:00',
   'timezone_type' => 3,
   'timezone' => 'America/Los_Angeles',
))
>> $end_dt->setTimestamp(strtotime('1-Mar-2012'))
DateTime::__set_state(array(
   'date' => '2012-03-01 00:00:00',
   'timezone_type' => 3,
   'timezone' => 'America/Los_Angeles',
))
>> $interval = $start_dt->diff($end_dt)
DateInterval::__set_state(array(
   'y' => 0,
   'm' => 0,
   'd' => 30,
   'h' => 0,
   'i' => 0,
   's' => 0,
   'invert' => 0,
   'days' => 30,
))
>> $interval->format('%mm %dd')
'0m 30d'
Run Code Online (Sandbox Code Playgroud)

即,31-Jan-20121-Mar-2012收益率不到一个月的时间!我希望输出为1个月,1天.2月份的天数无关紧要; 这是使用时间库的重点 - 它应该处理这些事情.WolframAlpha同意.

我应该向PHP提交错误吗?是否有一个hack/fix/workaround让几个月按预期工作?

Jon*_*Jon 6

更新的答案

这种行为DateTime::diff当然是意料之外的,但它不是一个bug.简而言之,diff如果您这样做,则返回年,月,日等

$end_ts = strtotime('+$y years +$m months +$d days' /* etc */, $start_ts);
Run Code Online (Sandbox Code Playgroud)

你会得到与最终原始结束日期相对应的时间戳.

这些添加是"盲目地"执行,然后适用日期更正(例如,1月31日+ 1个月将是2月31日,根据年份更正为3月2日或3月3日).在这个具体的例子中,你甚至不能添加一个月,因为salathe也解释说.


sal*_*the 5

我应该向PHP提交错误吗?

没有.

间隔的"月"部分意味着开始日期的月份部分可以增加那么多个月.PHP中的行为,取你的开始日期31-Jan-2012和递增月份(字面意思31-Feb-2012),然后纠正一个有效的日期(PHP为你做这个)将给出02-Mar-2012哪个晚于你正在使用的目标日期.

为了证明这一点,请记录您的开始日期,并在几个月内添加n个月以查看行为.

31-Jan-2012 (Interval)
02-Mar-2012 (P1M)
31-Mar-2012 (P2M)
01-May-2012 (P3M)
31-May-2012 (P4M)
01-Jul-2012 (P5M)
Run Code Online (Sandbox Code Playgroud)

您可以看到月份正在递增,然后进行调整以生成有效日期.