php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #64992 dst not handled past 2038
Submitted: 2013-06-08 06:45 UTC Modified: 2021-04-06 19:52 UTC
Votes:13
Avg. Score:4.4 ± 0.9
Reproduced:11 of 11 (100.0%)
Same Version:0 (0.0%)
Same OS:11 (100.0%)
From: eclipsechasers2 at yahoo dot com Assigned: derick (profile)
Status: Closed Package: Date/time related
PHP Version: 5.4.16 OS: Windows and Linux
Private report: No CVE-ID: None
 [2013-06-08 06:45 UTC] eclipsechasers2 at yahoo dot com
Description:
------------
This could be considered a duplicate of bug 42842. That bug was marked suspended in 2007. The reasons for its suspension are no longer valid. I updated that ticket, but, after a week with no feedback whatsoever, am opening a new ticket in the hope that it will get a reply. PHP does not handle dst transitions from the year 2038 on. This happens on Windows and Linux, on 32- and 64-bit systems. It happens with all releases, including the most current (5.4.16), and even when PECL is used to install timezonedb. The reason the ticket was suspended was "the timezone database simply doesn't have the resolution to store anything outside of the signed integer range for now." That is no longer true, and a 5-year delay seems time enough to implement it in PHP. The Unix zdump command handles the transition on 64-bit Linux systems (including the latest Ubuntu). Perl handles the transition on Windows and Linux, even on 32-bit systems.

Test script:
---------------
<?php
$firstyear = 2035;
$lastyear = 2040;
$tz = 'America/Los_Angeles';
date_default_timezone_set('America/Los_Angeles');
$dt = new DateTime((string) ($firstyear - 1) . "-07-02");
$di = new DateInterval('P6M');
for ($i = 0; $i < ($lastyear - $firstyear) * 2; $i++) {
  $dt->add($di);
  $gmto = $dt->getOffset();
  echo "Time Zone offset for $tz for " , $dt->format('Y-m-d') , " is $gmto\n";
}
?>

Expected result:
----------------
Time Zone offset for America/Los_Angeles for 2035-01-02 is -28800
Time Zone offset for America/Los_Angeles for 2035-07-02 is -25200
Time Zone offset for America/Los_Angeles for 2036-01-02 is -28800
Time Zone offset for America/Los_Angeles for 2036-07-02 is -25200
Time Zone offset for America/Los_Angeles for 2037-01-02 is -28800
Time Zone offset for America/Los_Angeles for 2037-07-02 is -25200
Time Zone offset for America/Los_Angeles for 2038-01-02 is -28800
Time Zone offset for America/Los_Angeles for 2038-07-02 is -25200
Time Zone offset for America/Los_Angeles for 2039-01-02 is -28800
Time Zone offset for America/Los_Angeles for 2039-07-02 is -25200

Actual result:
--------------
Time Zone offset for America/Los_Angeles for 2035-01-02 is -28800
Time Zone offset for America/Los_Angeles for 2035-07-02 is -25200
Time Zone offset for America/Los_Angeles for 2036-01-02 is -28800
Time Zone offset for America/Los_Angeles for 2036-07-02 is -25200
Time Zone offset for America/Los_Angeles for 2037-01-02 is -28800
Time Zone offset for America/Los_Angeles for 2037-07-02 is -25200
Time Zone offset for America/Los_Angeles for 2038-01-02 is -28800
Time Zone offset for America/Los_Angeles for 2038-07-02 is -28800
Time Zone offset for America/Los_Angeles for 2039-01-02 is -28800
Time Zone offset for America/Los_Angeles for 2039-07-02 is -28800

The lines for 2038-07-2 and 2039-07-02 are wrong; they should show -25200.
A zdump command which shows the correct values is:
zdump  -v -c 2035,2039 America/Los_Angeles 
Here is an equivalent Perl script which displays all the lines correctly:
#!/usr/bin/perl -w
use strict;
use DateTime;
my $firstyear = 2035;
my $lastyear = 2040;
my $tz = 'America/Los_Angeles';
my $dt = DateTime->new(year=>($firstyear - 1), month=>7, day=>2, time_zone=>$tz);
for (my $i = 0; $i < ($lastyear - $firstyear) * 2; $i++) {
  $dt->add(months=>6);
  my $gmto = $dt->offset();
  printf "Time Zone offset for $tz for " . $dt->ymd('-') . " is $gmto\n";
}

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-01-13 16:03 UTC] heiglandreas@php.net
As DST can change at any time due to politcal reasons it is not safe to calculate DST for multiple years in advance. This is not a limitation of PHP or the used timezoneDB but of the fact that DST is handled on a political level.

This is therefore not a bug in PHP.

For more details see https://andreas.heigl.org/2016/12/22/why-not-to-convert-a-datetime-to-timestamp/
 [2017-01-13 16:04 UTC] heiglandreas@php.net
-Status: Open +Status: Not a bug
 [2017-01-13 16:04 UTC] heiglandreas@php.net
See previous comment
 [2017-01-14 16:30 UTC] eclipsechasers2 at yahoo dot com
Nonsense! Given the correct information, I can decide on my own whether it is advisable to use it. Given incorrect information, I can't do anything. PHP WILL have this problem at the epoch change (ALL current times will be unreliable); it probably has others. You can go into panic mode and try to fix them all at once as the deadline looms. Or you can handle them in a sane manner, fixing them as they are identified well in advance of any deadline.
 [2018-04-24 09:53 UTC] paul dot crovella at gmail dot com
> As DST can change at any time due to politcal reasons it is not safe to calculate DST for multiple years in advance. This is not a limitation of PHP or the used timezoneDB but of the fact that DST is handled on a political level.

> This is therefore not a bug in PHP.

Whatever your thoughts are on the safety of this, there's nothing that makes a 2038 cutoff special other than the previous limitation of the timezone database. Since that limitation apparently no longer applies keeping 2038 as the cutoff is entirely arbitrary.

PHP should make available what is reasonable technically and leave the decision to the developer.
 [2018-04-26 11:03 UTC] pmmaga@php.net
-Status: Not a bug +Status: Re-Opened
 [2018-04-26 11:03 UTC] pmmaga@php.net
I agree with the reporter and Paul that currently, there is no good reason for PHP to keep this behavior. It is an arbitrary restriction.
 [2018-06-26 04:29 UTC] mlambley at gmail dot com
For me, the question isn't whether or not it "safe to assume so far in advance". The fact is that my system is broken right now because PHP's behaviour is inconsistent.

My system receives a DateTime object with time zone, converts using ->format('c'), and writes to the database. Beyond 2037, it records the date one day behind. Because instead of writing midnight+10:00 it writes midnight+11:00 which is 11pm the previous night.

My workaround is to create another DateTime object with a fixed pre-2037 date, compare the time zones, and adjust the date accordingly. It should not be necessary, because PHP's behaviour should be consistent.

Thank you for your time and attention to this ticket.
 [2019-05-24 20:08 UTC] zane at collected dot team
I agree with mlambley, this shouldn't be an issue of political whims or safety of assumptions, this should be about consistency. 2038 is only 19 years away, it is not unreasonable to get information about dates and times that are that close. PHP is the backbone for a large percentage of the internet, this is a major issue and needs to be fixed.


I'm working on a scheduling system that uses UTC timestamps and DateTime to create dates, schedules, events, etc. But since PHP won't calculate DST past 2037 my site is literally broken for my users. There are definitely workarounds for this, but that it literally the reason DateTime exists...
 [2019-05-28 09:44 UTC] derick@php.net
What would be an appropriate end time, considering that the more data we add, the larger the PHP binaries will get.
 [2020-06-09 14:28 UTC] tyler at mitton dot ca
Derick, if this cannot be fixed in a way that makes it go on indefinitely, then I would suggest that a *more* appropriate end time would be anything after 2038... I'll throw out 2100 as it seems to make a lot more sense than 2038 which is not that far away.

I cannot believe this is still an issue in 2020.
 [2020-08-18 14:21 UTC] sander at recras dot nl
Just ran into this issue. For API testing, we often use dates far in the future. Apparently, 2038-08-18 was too far for a new test. A time that should be represented as +02:00 was represented as +01:00.
This may not be a big issue yet, but given how long this bug has been open (42842 was opened nearly 13 years ago), let's hope it won't take another 13 years because then it will get annoying.
 [2021-04-06 19:52 UTC] derick@php.net
-Status: Re-Opened +Status: Closed -Assigned To: +Assigned To: derick
 [2021-04-06 19:52 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-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 23:01:28 2024 UTC