Is this a bug in PHP's DateTime:diff?
date, date-math, datetime, php, time
Solution
Should I file a bug to PHP?
No.
The "month" part of the interval means that the month part of the start date can be incremented by that many months. The behaviour in PHP, taking your start date of `31-Jan-2012` and incrementing the month (literally, `31-Feb-2012`) and then correcting for a valid date (PHP does this for you) would give `02-Mar-2012` which is later than the target date that you are working with.
To demonstrate this, take your start date and add n months for a few months to see the behaviour.
31-Jan-2012 (Interval)
02-Mar-2012 (P1M)
31-Mar-2012 (P2M)
01-May-2012 (P3M)
31-May-2012 (P4M)
01-Jul-2012 (P5M)
You can see that the month is being incremented, then adjusted to make a valid date.
Problem
``` >> $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' ``` i.e., `31-Jan-2012` to `1-Mar-2012` yields less than a month! I'd expect the output to be 1 month, 1 day. It shouldn't matter the number of days in February; that's the point of using a time library -- it's supposed to handle these things. WolframAlpha agrees. Should I file a bug to PHP? Is there a hack/fix/workaround to get months to work as expected?