Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP's DateTime::Diff gets it wrong?

DateTime::Diff should calculate a proper interval and take into account Daylight Savings Time (DST) and leap years. Although apparently it isn't so. Code of horror:

$d1 = new DateTime("2011-10-30 01:05:00", new DateTimeZone("Europe/Stockholm"));
$d2 = new DateTime("2011-10-30 03:05:00", new DateTimeZone("Europe/Stockholm"));

echo $d1->getOffset() / (60 * 60);

Prints '2'! Keep in mind thus that UTC time = 1h - 2h = 23:05:00 the day before.

echo $d2->getOffset() / (60 * 60);

Prints '1'. DST happened. UTC time = 3h - 1h = 02:05:00.

$di = $d1->diff($d2);
echo "Hours of DateInterval: " . $di->h;

Prints '2'! Wrong?

$hoursofdiff = ($d2->getTimeStamp() - $d1->getTimeStamp()) / 60 / 60;
echo "Calculated difference in hours: $hoursofdiff";

Prints '3'! Correct?

When the clock turned 03:00:00 at the given date, all Swedes turned their clock back one hour to 02:00:00. That means that total amount passed between 01:05 until 03:05 is three hours, much like the manual calculation echo'ed when using the UNIX TimeStamp. And much like we calculates on our fingers if we use an analogue clock. Even more so when we calculate the difference between the two UTC timestamps I got using PHP's own logic of offsets (!).

Is it PHP or have my brain ceased to work properly? A reprimand from anyone of you all gods that exist on this site would make me so happy!

I'm using PHP 5.4 (VC9) on an Apache-server. Unfortunately I use Windows 7 x64 as OS. I have tested my setup against all claims of bugs in PHP's Date/Time classes (there are a couple related to Windows) and can confirm that my system have none of them. Except from the above stated code I have not found any other errors. I pretty much validated all code and output the book "PHP Architect's guide to date and time programming" had to offer. Therefore I must conclude it has to be my brain witch has defaulted but I thought I'd give it a shoot here first.

like image 368
Martin Andersson Avatar asked Mar 14 '12 04:03

Martin Andersson


2 Answers

Do enjoy this list of related bugs in the PHP DateTime class, most of which have been open for 2+ years:

  • https://bugs.php.net/bug.php?id=40743
  • https://bugs.php.net/bug.php?id=49914
  • https://bugs.php.net/bug.php?id=51051
  • https://bugs.php.net/bug.php?id=51557
  • https://bugs.php.net/bug.php?id=52480
  • https://bugs.php.net/bug.php?id=54340
  • https://bugs.php.net/bug.php?id=54655
  • https://bugs.php.net/bug.php?id=55253
  • https://bugs.php.net/bug.php?id=60873
  • https://bugs.php.net/bug.php?id=60960
  • https://bugs.php.net/bug.php?id=61022
  • https://bugs.php.net/bug.php?id=61311
  • https://bugs.php.net/bug.php?id=61530
  • https://bugs.php.net/bug.php?id=61955
like image 63
taiganaut Avatar answered Nov 08 '22 09:11

taiganaut


You're right, PHP currently doesn't handle DST transitions...

Bug reports #51051 (still open) and #55253 (fixed in PHP 5.3.9) describe the problems you're having.

Daniel Convissor has written an RFC trying to address the issue a while back but the change-logs don't suggest this has been addressed. I was hoping this would fixed in 5.4 but I don't see any evidence it has been.

When/if it is implemented, it looks like you'll have to append "DST" or "ST" to the time string.

Best practice is to do all your date calculations in UTC, which avoids this problem.

This DST best practices post is very informative too.

like image 24
jmlnik Avatar answered Nov 08 '22 10:11

jmlnik