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: 2018-04-26 11:03 UTC
Votes:6
Avg. Score:4.5 ± 0.8
Reproduced:4 of 4 (100.0%)
Same Version:0 (0.0%)
Same OS:4 (100.0%)
From: eclipsechasers2 at yahoo dot com Assigned:
Status: Re-Opened Package: Date/time related
PHP Version: 5.4.16 OS: Windows and Linux
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: eclipsechasers2 at yahoo dot com
New email:
PHP Version: OS:

 

 [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.
 
PHP Copyright © 2001-2018 The PHP Group
All rights reserved.
Last updated: Sat Nov 17 02:01:25 2018 UTC