|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[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"
Patchesbug51051test.php.txt (last revision 2010-12-25 01:26 UTC by danielc@php.net)Pull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 02:00:01 2025 UTC |
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 2011Think 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)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/LinuxDateTime::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-wrongStill 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!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 CDTThis 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:59Still 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)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/LjubljanaStill 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