user2723490
user2723490

Reputation: 2100

PHP date interval - wrong month difference

Have a look at this code:

  $first = DateTime::createFromFormat('Y-m', '2001-07');
  $last = DateTime::createFromFormat('Y-m', '1998-06');
  $interval = $first->diff($last);
  echo "m diff: ".$interval->m." y diff: ".$interval->y."\n";

The output is m diff: 0 y diff: 3

Why does it return a wrong month difference?

Interesting that if I change dates as '2001-08' and '1998-07', it returns a correct month interval ==1.

Thanks!

Upvotes: 5

Views: 1961

Answers (2)

clintcloud
clintcloud

Reputation: 1

I know this is old, maybe this may help someone out there:

$first = DateTime::createFromFormat('Y-m', '2001-07');
$last = DateTime::createFromFormat('Y-m', '1998-06');
$interval = $first->diff($last);
$num_months = (($interval->y) * 12) + ($interval->m);

Explanation : convert $interval->y which is the year to months by multiplying it by 12 and add the succeeding months which is $interval->m

Upvotes: 0

hobbs
hobbs

Reputation: 239771

PHP DateTime doesn't handle incomplete datetimes.

DateTime::createFromFormat('Y-m', '2011-07') gives a DateTime that has a year of 2011, a month of 7, and a day, hour, minute and second taken from the current time (at the moment I write this, 2011-07-31 18:05:47.

Likewise, DateTime::createFromFormat('Y-m', '1998-06') gives a DateTime that has a year of 1998, a month of 6, and a day, hour, minute, and second taken from the current time. Since June 31st is a nonexistent date, the result is 1998-07-01 18:05:47 (31 days after the day before June 1st).

The difference between those two dates is then 3 years, 0 months, and 30 days.

In your example of 2001-08 and 1998-07, both months happen to have a 31st day, so the math comes out correctly. This bug is a difficult one to pin down, because it depends on the date that the code is run even though it doesn't obviously appear to.

You could probably fix your code by using a format of "Y-m-d H:i:s" and appending "-01 00:00:00" to each date you pass to createFromFormat, which will anchor the DateTime you get back to the beginning of the month.

Upvotes: 9

Related Questions