php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #63953 DateTime::diff produces a wrong DateInterval on DST change
Submitted: 2013-01-09 16:45 UTC Modified: 2017-01-16 06:45 UTC
Votes:17
Avg. Score:4.1 ± 0.9
Reproduced:17 of 17 (100.0%)
Same Version:5 (29.4%)
Same OS:7 (41.2%)
From: gianluca dot pinna at allbus dot com Assigned: heiglandreas (profile)
Status: Closed Package: Date/time related
PHP Version: 5.3.20 OS: Linux 64
Private report: No CVE-ID: None
 [2013-01-09 16:45 UTC] gianluca dot pinna at allbus dot com
Description:
------------
I have two dates, the second date is after a DST change.

I tried to get a diff between the two dates. Computing the difference between the 
timestamps I get the correct result (33 hours).

Using DateTime->diff() I get 34 hours. Is this expected?

Test script:
---------------
<?php

$originDate = new DateTime('2013-03-30 00:00:00', new DateTimeZone('Europe/Rome'));
$destinationDate = new DateTime('2013-03-31 10:00:00', new DateTimeZone('Europe/Rome'));


$diff = $destinationDate->getTimestamp() - $originDate->getTimestamp();
$dateinterval = $originDate->diff($destinationDate);

var_dump($diff/3600);
var_dump($dateinterval->d*24 + $dateinterval->h);

// int(33)
// int(34)

Expected result:
----------------
I would expect to always get 33 hours.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-02-05 17:42 UTC] kaido at tradenet dot ee
test script:

$d1 = new DateTime('2012-05-31');
$d2 = new DateTime('2013-03-02');

$diff1 = $d1->diff ($d2);

$diff2 = $d2->diff ($d1);

echo "case 1: ".$diff1->m." months, case 2: ".$diff2->m." months";


expected result:

both $diff1->m and $diff2->m are 9
 [2013-06-16 19:23 UTC] chris at modernmedia dot co
I can more or less confirm that DateInterval has 
Daylight Savings changes backward, at least for my 
2014 test cases. In the springtime in the US we 
spring forward at 2am on a Sunday morning. 
2am and 3am are the same exact time, and share the 
same exact timestamp. At 3am, 2 actual hours 
have elapsed since midnight.

In the fall we fall backward on a Sunday at 2am. 
In this case, at 3am 4 actual hours have elapsed 
since midnight.

My code shows that DateTime and DateTimezone
handle DST changes correctly -- its DateInterval
that is having the problem.



Here's my test code:

<?php
/**
Daylight Saving Time (United States) 2014 begins at 2:00 AM on
Sunday, March 9
and ends at 2:00 AM on
Sunday, November 2
 */

$tz = new DateTimeZone( 'America/New_York');
$d1 = new DateTime('2014-03-09 00:00:00', $tz);


echo PHP_EOL;
echo 'Springing forward at 2am on Sunday, March 9, 2014...' . PHP_EOL;
for ($n = 0; $n < 7; $n++){
	$d2 = new DateTime(sprintf('2014-03-09 %s:00:00', $n), $tz);
	$ts_diff = ($d2->getTimestamp() - $d1->getTimestamp())/(60 * 60);
	$int = $d2->diff($d1);
	echo 'Comparing ' . $d2->format('g a') . ' to ' . $d1->format('g a') . 
PHP_EOL;
	echo 'Timestamp diff:          ' . $ts_diff . PHP_EOL;
	echo 'Interval diff:           ' . $int->h . PHP_EOL;

}
echo PHP_EOL;
$d1 = new DateTime('2014-11-02 00:00:00', $tz);
echo 'Falling backward at 2am on Sunday, November 2, 2014...' . PHP_EOL;
for ($n = 0; $n < 7; $n++){
	$d2 = new DateTime(sprintf('2014-11-02 %s:00:00', $n), $tz);
	$ts_diff = ($d2->getTimestamp() - $d1->getTimestamp())/(60 * 60);
	$int = $d2->diff($d1);
	echo 'Comparing ' . $d2->format('g a') . ' to ' . $d1->format('g a') . 
PHP_EOL;
	echo 'Timestamp diff:          ' . $ts_diff . PHP_EOL;
	echo 'Interval diff:           ' . $int->h . PHP_EOL;

}

phpinfo(INFO_GENERAL);
?>

Output
========

Springing forward at 2am on Sunday, March 9, 2014...
Comparing 12 am to 12 am
Timestamp diff:          0
Interval diff:           0
Comparing 1 am to 12 am
Timestamp diff:          1
Interval diff:           1
Comparing 2 am to 12 am
Timestamp diff:          2
Interval diff:           3
Comparing 3 am to 12 am
Timestamp diff:          2
Interval diff:           3
Comparing 4 am to 12 am
Timestamp diff:          3
Interval diff:           4
Comparing 5 am to 12 am
Timestamp diff:          4
Interval diff:           5
Comparing 6 am to 12 am
Timestamp diff:          5
Interval diff:           6

Falling backward at 2am on Sunday, November 2, 2014...
Comparing 12 am to 12 am
Timestamp diff:          0
Interval diff:           0
Comparing 1 am to 12 am
Timestamp diff:          1
Interval diff:           1
Comparing 2 am to 12 am
Timestamp diff:          3
Interval diff:           2
Comparing 3 am to 12 am
Timestamp diff:          4
Interval diff:           3
Comparing 4 am to 12 am
Timestamp diff:          5
Interval diff:           4
Comparing 5 am to 12 am
Timestamp diff:          6
Interval diff:           5
Comparing 6 am to 12 am
Timestamp diff:          7
Interval diff:           6
phpinfo()
PHP Version => 5.4.9

System => Darwin Christophers-MacBook-Air.local 12.4.0 Darwin Kernel Version 
12.4.0: Wed May  1 17:57:12 PDT 2013; root:xnu-2050.24.15~1/RELEASE_X86_64 x86_64
Build Date => Dec 11 2012 12:36:33
 [2013-11-06 17:30 UTC] alvaro at demogracia dot com
Yet another test script:

<?php

$zone = new DateTimeZone('Europe/Madrid');
$start = new DateTime('2013-03-31 1:59:00 ', $zone);
$end = new DateTime('2013-03-31 3:00:00', $zone);

$difference = $start->diff($end);
echo $difference->format('%H:%I:%S') . PHP_EOL;

$start->setTimeZone(new DateTimeZone('UTC'));
$end->setTimeZone(new DateTimeZone('UTC'));
$difference = $start->diff($end);
echo $difference->format('%H:%I:%S') . PHP_EOL;

?>

Expected output:

00:01:00
00:01:00

Actual output:

01:01:00
00:01:00
 [2014-01-22 14:13 UTC] perrier dot p at gmail dot com
The easy way to see the difference :
http://3v4l.org/ab0Hm#v5424


The code 
<?php

$debut = mktime(0, 0, 0, 10, 27, 2013);
$fin = mktime(23, 59, 59, 11, 10, 2013);

$d1 = new DateTime('now',new DateTimeZone('Europe/Paris'));
$d2 = new DateTime('now',new DateTimeZone('Europe/Paris'));
$d1->setTimestamp($debut);
$d2->setTimestamp($fin);
$diff = $d1->diff($d2);

print_r($diff);
 [2015-02-17 22:29 UTC] dev dot anubis at gmail dot com
Duplicate of #63442
 [2015-02-18 08:14 UTC] alvaro at demogracia dot com
This looks already fixed in PHP/5.6.0 (2014-08-28) and backport versions released on 2014-09-01: PHP/5.4.24 and PHP/5.5.8

http://3v4l.org/MVWMG
 [2017-01-16 06:45 UTC] heiglandreas@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: heiglandreas
 [2017-01-16 06:45 UTC] heiglandreas@php.net
Looks like this has been fixed.
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC