2

While playing with PHP, I strucked on this :

<?php

$FebruaryTheFirst = \DateTime::createFromFormat('Y-m-d H:i:s', '2001-02-01 00:00:00');
$MarchTheSecond = \DateTime::createFromFormat('Y-m-d H:i:s', '2001-03-01 00:00:00');

$interval = $FebruaryTheFirst->diff($MarchTheSecond);

echo $interval->m.PHP_EOL; // Outputs 0. WTF?

$FebruaryTheFirstbis = \DateTime::createFromFormat('Y-m-d', '2001-02-01');
$MarchTheSecondbis = \DateTime::createFromFormat('Y-m-d', '2001-03-01');

$interval2 = $FebruaryTheFirstbis->diff($MarchTheSecondbis);

echo $interval2->m.PHP_EOL; // Outputs 1. WTF?

$FebruaryTheFirstter = \DateTime::createFromFormat('Y-m-d H:i:s', '2001-02-01 00:01:00');
$MarchTheSecondter = \DateTime::createFromFormat('Y-m-d H:i:s', '2001-03-02 00:01:00');

$interval3 = $FebruaryTheFirstter->diff($MarchTheSecondter);

echo $interval3->m.PHP_EOL; // Outputs 0. WTF?

$FebruaryTheFirstfour = \DateTime::createFromFormat('Y-m-d H:i:s', '2001-02-01 01:00:00');
$MarchTheSecondfour = \DateTime::createFromFormat('Y-m-d H:i:s', '2001-03-02 01:00:00');

$interval4 = $FebruaryTheFirstfour->diff($MarchTheSecondfour);

echo $interval4->m.PHP_EOL; // Outputs 1. WTF?

Question

I should always get 1 as output, as I'm always counting the number of month between Februar, 1st and March, 1st. But as shown previously, I also get 0 => WTF?

For information my version of php is

PHP 5.3.8 (cli) (built: Jan 12 2012 19:12:32) Copyright (c) 1997-2011
The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2011 Zend
Technologies with Xdebug v2.1.1, Copyright (c) 2002-2011, by Derick Rethans
Clement Herreman
  • 10,274
  • 4
  • 35
  • 57
  • 1
    what is your question exactly – Rene Pot Feb 06 '12 at 16:24
  • @Topener: I edited to be more precise. My question is why does the output change, where the argument aren't. – Clement Herreman Feb 06 '12 at 16:49
  • I am unable to duplicate this behaviour on 5.3.6 and 5.4.0-rc7, 1s straight across the board. – Charles Feb 06 '12 at 16:52
  • @ClementHerreman - The problem seems to be related to the timezone. When I use my local timezone (America/Vancouver), it outputs 1 for all 4 but when I use a different one (Australia/Sydney), it outputs 0. I don't have the time to look into this at the moment but I hope this points you in the right direction. Have a look at [this sample](http://codepad.viper-7.com/Apn3BH) and [this sample](http://codepad.viper-7.com/CgRdFo). I also looks like someone left a comment in the [`DateTime::diff()` documentation](http://www.php.net/manual/en/datetime.diff.php#101990) that it's inaccurate. – Francois Deschenes Feb 06 '12 at 16:53

1 Answers1

3

It looks like this is a known bug in PHP. Have a look at the bug report. The only way to fix this, at least for now, is to work in UTC to eliminate local timezone issues.

Example:

// Get the current timezone.
$originalTimezone = @date_default_timezone_get();

// Work in UTC.
date_default_timezone_set('UTC');

// ...
$dateStart = new DateTime('2001-02-01');
$dateEnd   = new DateTime('2001-03-01');
$interval = $dateStart->diff($dateEnd);

// Reset the timezone.
if ($originalTimezone) {
    date_default_timezone_set($originalTimezone);
}
Francois Deschenes
  • 24,816
  • 4
  • 64
  • 61