php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80664 DateTime objects behave incorrectly around DST transition
Submitted: 2021-01-24 21:53 UTC Modified: 2021-04-06 19:57 UTC
From: AaronB at landproDATA dot com Assigned: derick (profile)
Status: Closed Package: Date/time related
PHP Version: 7.3.26 OS: Irrelevant
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: AaronB at landproDATA dot com
New email:
PHP Version: OS:

 

 [2021-01-24 21:53 UTC] AaronB at landproDATA dot com
Description:
------------
DateTime::add() behaves incorrectly when adding times to a DateTime representing a point during the hour that is repeated during a transition from daylight savings time to standard time. This problem seems to arise only in cases where the associated DateTimeZone has been defined using a geographical label like 'America/Boise'.

One thing that is especially surprising in these cases is that using DateTime::add() to add an hour to a time can cause the description of the timezone that is reported by the 'T' format option to change in such a way that the operation appears to have succeed as intended while the call to DateTime::add() actually leaves the underlying Unix timestamp entirely unchanged. What this means is that there is a bug in DateTime::format(), as well as in DateTime::add().

I have verified that this problem occurs in PHP 7.3.21 and PHP 7.4.0.

Test script:
---------------
$dt = new DateTime('@1604215800');
$dt->setTimezone(new DateTimeZone('America/Boise'));
echo "{$dt->format('Y-m-d H:i:s T')} | {$dt->getTimestamp()}\r\n";
$dt->add(new DateInterval('PT1H'));
echo "{$dt->format('Y-m-d H:i:s T')} | {$dt->getTimestamp()}\r\n";
$dt->add(new DateInterval('PT1H'));
echo "{$dt->format('Y-m-d H:i:s T')} | {$dt->getTimestamp()}\r\n";
$dt->add(new DateInterval('PT1M'));
echo "{$dt->format('Y-m-d H:i:s T')} | {$dt->getTimestamp()}\r\n";


Expected result:
----------------
2020-11-01 01:30:00 MDT | 1604215800
2020-11-01 01:30:00 MST | 1604219400
2020-11-01 02:30:00 MST | 1604223000
2020-11-01 02:31:00 MST | 1604223060


Actual result:
--------------
2020-11-01 01:30:00 MDT | 1604215800
2020-11-01 01:30:00 MST | 1604215800
2020-11-01 01:30:00 MST | 1604215800
2020-11-01 01:31:00 MDT | 1604215860


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-01-24 22:27 UTC] AaronB at landproDATA dot com
-Summary: DateTime::add() behaves incorrectly at DST transition +Summary: DateTime objects behave incorrectly around DST transition
 [2021-01-24 22:27 UTC] AaronB at landproDATA dot com
After more testing, I discovered that, at these problematic transition points, changing the DateTimeZone of a DateTime object can actually change the underlying Unix timestamp -- which, as far as I know, should never happen. So, this bug report can also be regarded as reporting a bug in the DateTime::setTimezone() function.

Here is an example that illustrates the problem:

$dt = new DateTime('@1604219400');
$dt->setTimezone(new DateTimeZone('UTC'));
echo "{$dt->format('Y-m-d H:i:s T')} | {$dt->getTimestamp()}\r\n";
$dt->setTimezone(new DateTimeZone('America/Boise'));
echo "{$dt->format('Y-m-d H:i:s T')} | {$dt->getTimestamp()}\r\n";

Expected result:
----------------
2020-11-01 08:30:00 UTC | 1604219400
2020-11-01 01:30:00 MST | 1604219400

Actual result:
--------------
2020-11-01 08:30:00 UTC | 1604219400
2020-11-01 01:30:00 MST | 1604215800
 [2021-04-06 19:57 UTC] derick@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: derick
 [2021-04-06 19:57 UTC] derick@php.net
The fix for this bug has been committed.
If you are still experiencing this bug, try to check out latest source from https://github.com/php/php-src and re-test.
Thank you for the report, and for helping us make PHP better.

Fixed for PHP 8.1.
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Mon Apr 19 16:01:26 2021 UTC