php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76983 date('i') returns wrong value for Dublin timezone
Submitted: 2018-10-08 06:38 UTC Modified: 2018-10-09 09:27 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: tomas at matrixinternet dot ie Assigned:
Status: Not a bug Package: Date/time related
PHP Version: 5.6.38 OS: Ubuntu 16.04
Private report: No CVE-ID: None
 [2018-10-08 06:38 UTC] tomas at matrixinternet dot ie
Description:
------------
We use date('I') (capital i) to detect daylight saving time being in action or not. It kept returning "1" quite happily throughout the summer. On 29/09/2018 around 7:00 am, it started returning "0", indicating a change to a winter time. This happened pretty much exactly one full month before the change was about to happen on October 29.

Linux Timezone is: Europe/Dublin (IST, +0100) PHP timezone is set via date_default_timezone_set('Europe/Dublin');

date('I', strtotime('2018-09-29 02:00:00')) // returns "0" - which is wrong as DST is active now!

date('I', strtotime('2018-11-29 02:00:00')) // returns "1" - which is wrong as DST is Summer time!

This issue seems to happen specifically on Amazon AWS EC2 instances.
A newly installed server instance returns the correct value for around a day, but then it seems to switch over.
We weren't able to replicate this issue on a non-AWS instance.


Test script:
---------------
date_default_timezone_set('Europe/London');
if (date('I', strtotime('2018-09-29 02:00:00'))) {
	echo 'We are in DST!';
} else {
	echo 'We are not in DST!';
}
date_default_timezone_set('Europe/Dublin');
if (date('I', strtotime('2018-09-29 02:00:00'))) {
	echo 'We are in DST!';
} else {
	echo 'We are not in DST!';
}
date_default_timezone_set('Europe/Paris');
if (date('I', strtotime('2018-09-29 02:00:00'))) {
	echo 'We are in DST!';
} else {
	echo 'We are not in DST!';
}

Expected result:
----------------
We are in DST!
We are in DST!
We are in DST!

Actual result:
--------------
We are in DST!
We are not in DST!
We are in DST!

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-10-08 06:52 UTC] requinix@php.net
-Status: Open +Status: Feedback
 [2018-10-08 06:52 UTC] requinix@php.net
It looks like tzdata had issues with the way it stored DST information for Europe/Dublin. What version of tzdata do you have installed? Is it at least 2018e?
 [2018-10-08 08:42 UTC] tomas at matrixinternet dot ie
Yes, tzdata version on the affected system is 2018e.
 [2018-10-09 06:04 UTC] requinix@php.net
The next question is whether you can reproduce with PHP 7.1, given that 5.6 and even 7.0 are no longer supported.

And what are the precise version numbers of your tzdata on the AWS and non-AWS (presumably also 16.04) instances?
 [2018-10-09 09:27 UTC] derick@php.net
-Status: Feedback +Status: Not a bug
 [2018-10-09 09:27 UTC] derick@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

I don't think this is a bug. Ireland, for some historical reason, has defined their UTC+1 as Irish Standard Time — the legal "default" time offset. During the winter period, they have a negative DST offset of -1 hour, to get back to UTC-0. This happens at the exact times when the UK goes from GMT (winter time) to BST (British Summer Time). There is more info at https://github.com/eggert/tz/blob/master/europe#L369-L383, and the rules are at https://github.com/eggert/tz/blob/master/europe#L529-L557

This is a fairly recent change in the tzdata package (2018e, https://github.com/eggert/tz/commit/127b4af7219e6df9253b34e390797c5527b8cc66), which does show these transition times:

Europe/Dublin  Sun Mar 26 00:59:59 2017 UT = Sun Mar 26 00:59:59 2017 GMT isdst=1 gmtoff=0
Europe/Dublin  Sun Mar 26 01:00:00 2017 UT = Sun Mar 26 02:00:00 2017 IST isdst=0 gmtoff=3600
Europe/Dublin  Sun Oct 29 00:59:59 2017 UT = Sun Oct 29 01:59:59 2017 IST isdst=0 gmtoff=3600
Europe/Dublin  Sun Oct 29 01:00:00 2017 UT = Sun Oct 29 01:00:00 2017 GMT isdst=1 gmtoff=0
Europe/Dublin  Sun Mar 25 00:59:59 2018 UT = Sun Mar 25 00:59:59 2018 GMT isdst=1 gmtoff=0
Europe/Dublin  Sun Mar 25 01:00:00 2018 UT = Sun Mar 25 02:00:00 2018 IST isdst=0 gmtoff=3600
Europe/Dublin  Sun Oct 28 00:59:59 2018 UT = Sun Oct 28 01:59:59 2018 IST isdst=0 gmtoff=3600
Europe/Dublin  Sun Oct 28 01:00:00 2018 UT = Sun Oct 28 01:00:00 2018 GMT isdst=1 gmtoff=0

I bet that when you first install an AWS instance, it doesn't have 2018e yet, and it auto-updates to 2018e a while later.

PHP picks up the data from the tzdata project, either through a built-in version of the database, or through the system updates. In both cases, IST would now see isdst=1 for the winter (non-Standard) period. This is the correct behaviour, albeit unwanted in your case I suppose.

What are you exactly trying to accomplish by checking for the dst flag? As a side note, it's probably be better to check this *not* by using date("I"), but instead use DateTimeZone::getTransitions with the current timestamp:

<?php
$tz = new DateTimeZone( 'Europe/Dublin' );
$transitions = $tz->getTransitions(time(), strtotime("+3 months"));
print_r($transitions);
?>

Output:

Array
(
    [0] => Array
        (
            [ts] => 1539077227
            [time] => 2018-10-09T09:27:07+0000
            [offset] => 3600
            [isdst] => 
            [abbr] => IST
        )

    [1] => Array
        (
            [ts] => 1540688400
            [time] => 2018-10-28T01:00:00+0000
            [offset] => 0
            [isdst] => 1
            [abbr] => GMT
        )

)


— This of course, will give the same answer.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 26 09:01:29 2024 UTC