php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #51051 DateTime modify wrong result with DST change
Submitted: 2010-02-15 10:55 UTC Modified: 2017-03-19 10:10 UTC
Votes:39
Avg. Score:4.7 ± 0.6
Reproduced:36 of 36 (100.0%)
Same Version:9 (25.0%)
Same OS:23 (63.9%)
From: mehdi dot rande at aliasource dot fr Assigned: derick (profile)
Status: Duplicate Package: Date/time related
PHP Version: 7.0.8 OS: all
Private report: No CVE-ID: None
 [2010-02-15 10:55 UTC] mehdi dot rande at aliasource dot fr
Description:
------------
When adding seconds (or minutes or hours) to a datetime via the modify 
method, if the date before modification is before the DST change and the 
date after modification is after the DST change, the date after 
modification will be wrong.
php 5.2 seems to be affected too.

Reproduce code:
---------------
<?php
$dateBefore = new DateTime("2012-10-27 12:00:00", new DateTimezone("Europe/Paris"));
var_dump($dateBefore->format('c'));
// DST change : 2012-10-28 01:00:00
$dateAfter = new DateTime("2012-10-28 12:00:00", new DateTimezone("Europe/Paris"));
var_dump($dateAfter->format('c'));
$diff = $dateAfter->format('U') - $dateBefore->format('U');
var_dump($diff); // === 25 hours, 
$dateBefore->modify('+'.$diff.' seconds');
var_dump($dateBefore->format('c'));
?>

Expected result:
----------------
string(25) "2012-10-27T12:00:00+02:00"
string(25) "2012-10-28T12:00:00+01:00"
int(90000)
string(25) "2012-10-28T13:00:00+01:00"


Actual result:
--------------
string(25) "2012-10-27T12:00:00+02:00"
string(25) "2012-10-28T12:00:00+01:00"
int(90000)
string(25) "2012-10-28T12:00:00+01:00"


Patches

bug51051test.php.txt (last revision 2010-12-25 01:26 UTC by danielc@php.net)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-02-15 10:56 UTC] mehdi dot rande at aliasource dot fr
Sorry the expected result is  in fact the actual result, and the actual 
result is the expected result.
 [2010-08-24 00:04 UTC] glennpratt at gmail dot com
Same issue here on PHP 5.3.2

<?php

$date = new DateTime('2011-03-13T03:00:00', timezone_open('America/Chicago'));
print($date->format('c e'));

$date->modify('-2 minutes');
print($date->format('c e'));

?>


Actual Result
-------------
2011-03-13T03:00:00-05:00 America/Chicago
2011-03-13T03:58:00-05:00 America/Chicago

Expected Result
---------------
2011-03-13T03:00:00-05:00 America/Chicago
2011-03-13T01:58:00-05:00 America/Chicago


Comparison: Ruby time library
-----------------------------
irb(main):015:0> date = Time.parse('2011-03-13T03:00:00 in CST')
=> Sun Mar 13 03:00:00 -0500 2011
irb(main):016:0> date - 120
=> Sun Mar 13 01:58:00 -0600 2011
 [2010-08-24 14:34 UTC] glennpratt+php at gmail dot com
Correction for the Expected result above.

Expected Result
---------------
2011-03-13T03:00:00-05:00 America/Chicago
2011-03-13T01:58:00-06:00 America/Chicago
 [2010-12-25 02:26 UTC] danielc@php.net
The following patch has been added/updated:

Patch Name: bug51051test.php.txt
Revision:   1293240376
URL:        http://bugs.php.net/patch-display.php?bug=51051&patch=bug51051test.php.txt&revision=1293240376
 [2010-12-25 02:27 UTC] danielc@php.net
I just attached a test script that covers issues in the spring and fall.
 [2010-12-25 02:46 UTC] danielc at analysisandsolutions dot com
DateTime::diff() is similarly afflicted with daylight/standard change over issues.  Naturally, diff/add/sub all need to be in sync so intervals returned by diff can be passed to add/sub and produce the original datetime.
 [2011-02-24 17:07 UTC] j dot ek at gmx dot net
Think I found a related issue, reproduce it with:

<?php
$dt = new DateTime('now', new DateTimeZone('Europe/Berlin'));

//  try to set timestamp of 2010-10-31T02:00:00+0200
$dt->setTimestamp(1288483200);

// but returns timestamp of 2010-10-31T02:00:00+0100
echo $dt->getTimestamp(); // outputs 1288486800
?>

WinXP 32, PHP 5.3.2 (cli) (built: Mar  3 2010 20:36:54)
 [2011-04-18 17:30 UTC] halde at freenet dot de
reproduced issue of previous poster on a linux machine (timestamps are not 
equal):

$ php -a
Interactive shell

php > $dt = new DateTime('now', new DateTimeZone('Europe/Berlin'));
php > $dt->setTimestamp(1288483200);
php > echo $dt->getTimestamp();
1288486800
php > echo phpversion();
5.3.3-1ubuntu9.3
php > exit

$ uname -a
Linux wum128229 2.6.35-28-generic #49-Ubuntu SMP Tue Mar 1 14:39:03 UTC 2011 
x86_64 GNU/Linux
 [2011-11-21 02:43 UTC] danielc@php.net
This will be addressed by
https://wiki.php.net/rfc/datetime_and_daylight_saving_time
 [2012-03-14 14:36 UTC] webmaster at martinandersson dot com
DateTime::diff get's it wrong in PHP 5.4. Tested on Apache (with PHP 5.4 VC9) / 
Windows 7 x64. 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"));

$di = $d1->diff($d2);
echo $di->h;

This produces '2' whereas it should have said '3' because in this timezone and 
interval (more precisly 03:00:00), all Swedes turned their clock back 1 hour. 
Still, the internal logic of PHP 5.4 knows about the different offsets:

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

Prints '2'.

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

Prints '1'.

A direct calculation with UNIX timestamps produces the correct result:

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

Prints '3'.

This issue has been further elaborated here:
http://stackoverflow.com/questions/9695870/phps-datetimediff-gets-it-wrong
 [2012-05-17 00:12 UTC] kavi at postpro dot net
See also:

https://bugs.php.net/bug.php?id=60960
https://bugs.php.net/bug.php?id=61530
https://bugs.php.net/bug.php?id=52480

Quoting https://wiki.php.net/rfc/datetime_and_daylight_saving_time -- "Getting 
these issues straightened out before 5.4 goes into Release Candidate status seems 
wise."
 [2013-03-19 18:09 UTC] kavi at postpro dot net
This is still broken in 5.3.21, according to danielc's test.

$ php --version
PHP 5.3.21 (cli) (built: Jan 17 2013 12:34:34) 
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2013 Zend Technologies

$ php derp.php 

SPRING INTERVALS (add okay, sub does not change hour)
  2010-03-14T01:59:59-05:00  America/New_York  EST  0  1268549999
Adding interval: PT1S
  2010-03-14T03:00:00-04:00  America/New_York  EDT  1  1268550000
Subtracting interval: PT1S
  2010-03-14T03:59:59-04:00  America/New_York  EDT  1  1268553599

SPRING TIMESTAMPS (works as expected)
  2010-03-14T01:59:59-05:00  America/New_York  EST  0  1268549999
Adding seconds: 1
  2010-03-14T03:00:00-04:00  America/New_York  EDT  1  1268550000
Subtracting seconds: 1
  2010-03-14T01:59:59-05:00  America/New_York  EST  0  1268549999

FALL INTERVALS (add and sub skip the 1am - 2am redo)
  2010-11-07T00:59:59-04:00  America/New_York  EDT  1  1289105999
Adding interval: PT1H
  2010-11-07T01:59:59-04:00  America/New_York  EDT  1  1289109599
Adding interval: PT1S
  2010-11-07T02:00:00-05:00  America/New_York  EST  0  1289113200
Subtracting interval: PT1S
  2010-11-07T01:59:59-04:00  America/New_York  EDT  1  1289109599

FALL TIMESTAMPS (works as expected)
  2010-11-07T00:59:59-04:00  America/New_York  EDT  1  1289105999
Adding seconds: 3600
  2010-11-07T01:59:59-04:00  America/New_York  EDT  1  1289109599
Adding seconds: 1
  2010-11-07T01:00:00-05:00  America/New_York  EST  0  1289109600
Adding seconds: 3600
  2010-11-07T02:00:00-05:00  America/New_York  EST  0  1289113200
Subtracting seconds: 1
  2010-11-07T01:59:59-05:00  America/New_York  EST  0  1289113199
 [2013-05-30 14:56 UTC] joerg dot eichhorn at kiwigrid dot com
Still present with:

PHP 5.4.7 (cli) (built: Sep 12 2012 23:48:31)
Copyright (c) 1997-2012 The PHP Group

My former test script still shows the error:

<?php
$dt = new DateTime('now', new DateTimeZone('Europe/Berlin'));

//  try to set timestamp of 2010-10-31T02:00:00+0200
$dt->setTimestamp(1288483200);
echo   "Expected: 1288483200\n";

// but returns timestamp of 2010-10-31T02:00:00+0100
echo "Actual  : ".$dt->getTimestamp()."\n"; // outputs 1288486800

?>

Any Ideas when this issue is going to be fixed? It's a serious issue that it returns another timestamp than what was set!
 [2016-03-13 23:52 UTC] cvkline at gmail dot com
This bug is still present as of PHP 5.5.25!

$gd = new DateTime('2016-03-13 03:30:00');
echo $gd->format('Y-m-d H:i:s T') . "\n";
$gd->modify('-45 minutes');
echo $gd->format('Y-m-d H:i:s T') . "\n";

produces:

2016-03-13 03:30:00 CDT
2016-03-13 03:45:00 CDT
 [2016-07-19 09:26 UTC] dasistmeine-mail at gmx dot de
This bug is still present as of PHP 7.0.5!

$date = new DateTime('2017-03-26 1:59:59', new DateTimeZone('Europe/Berlin'));
echo $date->format('Y-m-d H:i:s') . PHP_EOL;
$date->modify('+ 1 second')->modify('- 1 second');
echo $date->format('Y-m-d H:i:s') . PHP_EOL;

expected:
2017-03-26 1:59:59
2017-03-26 1:59:59

actualy got:
2017-03-26 01:59:59
2017-03-26 03:59:59
 [2016-10-06 15:54 UTC] nicholas dot leon at wellsfargo dot com
Still present in PHP 5.5.23 (cli) (built: Apr  2 2015 05:29:14)

$oDate = new DateTime("11/6/2016 1:00:00am");
print($oDate->format('Y-m-d H:i:s').PHP_EOL);
$oDate->add(new DateInterval('PT1H')); 
print($oDate->format('Y-m-d H:i:s').PHP_EOL);

$ ./test2.php
2016-11-06 01:00:00
2016-11-06 01:00:00

Expected:
2016-11-06 01:00:00
2016-11-06 02:00:00 (or maybe 03:00:00 -- but definitely not 01:00:00)
 [2016-10-12 09:15 UTC] rado at max dot si
Still present in php 7.0.8

php -v

PHP 7.0.8-0ubuntu0.16.04.3 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.8-0ubuntu0.16.04.3, Copyright (c) 1999-2016, by Zend Technologies
    with Xdebug v2.4.0, Copyright (c) 2002-2016, by Derick Rethans

date_default_timezone_set('Europe/Ljubljana');
$d = new DateTime('2016-10-30 0000');
$newts = $d->getTimestamp() + 2 * 3600;    // 2h
$d->modify("+2 hour");      // it doesn't always give the right result
$dts = $d->getTimestamp();
echo " By adding 2 hours to " . date('Y-M-d H:i:s I e', $oldts) . " we get " . PHP_EOL;
echo "  Actual result       " . date('Y-M-d H:i:s I e', $newts) . PHP_EOL;
echo "  Expected result     " . date('Y-M-d H:i:s I e', $dts) . PHP_EOL;


 By adding 2 hours to 2017-Jan-01 01:00:00 0 Europe/Ljubljana we get 
  Actual result       2016-Oct-30 02:00:00 1 Europe/Ljubljana
  Expected result     2016-Oct-30 02:00:00 0 Europe/Ljubljana
 [2016-10-12 09:23 UTC] rado at max dot si
Still present in php 7.0.8

php -v

PHP 7.0.8-0ubuntu0.16.04.3 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.8-0ubuntu0.16.04.3, Copyright (c) 1999-2016, by Zend Technologies
    with Xdebug v2.4.0, Copyright (c) 2002-2016, by Derick Rethans
PHP 7.0.8-0ubuntu0.16.04.3 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.8-0ubuntu0.16.04.3, Copyright (c) 1999-2016, by Zend Technologies
    with Xdebug v2.4.0, Copyright (c) 2002-2016, by Derick Rethans

date_default_timezone_set('Europe/Ljubljana');
$d = new DateTime('2016-10-30 0000');
$oldts = $d->getTimestamp();
$newts = $d->getTimestamp() + 2 * 3600;    // 2h
$d->modify("+2 hour");      // it doesn't always give the right result
$dts = $d->getTimestamp();
echo " By adding 2 hours to " . date('Y-M-d H:i:s I e', $oldts) . " we get " . PHP_EOL;
echo "  Actual result       " . date('Y-M-d H:i:s I e', $newts) . PHP_EOL;
echo "  Expected result     " . date('Y-M-d H:i:s I e', $dts) . PHP_EOL;

 By adding 2 hours to 2016-Oct-30 00:00:00 1 Europe/Ljubljana we get 
  Actual result       2016-Oct-30 02:00:00 1 Europe/Ljubljana
  Expected result     2016-Oct-30 02:00:00 0 Europe/Ljubljana
 [2017-01-11 17:49 UTC] heiglandreas@php.net
-Operating System: Linux +Operating System: all -PHP Version: 5.3.1 +PHP Version: 7.0.8
 [2017-03-19 10:10 UTC] heiglandreas@php.net
-Status: Assigned +Status: Duplicate
 [2017-03-19 10:10 UTC] heiglandreas@php.net
We're tracking this now in https://bugs.php.net/bug.php?id=74274
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Oct 31 22:01:27 2024 UTC