php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #27533 gmmktime can return wrong value on the night that DST comes into affect
Submitted: 2004-03-08 21:27 UTC Modified: 2004-04-09 15:15 UTC
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:1 (50.0%)
From: scottmacvicar at ntlworld dot com Assigned:
Status: Closed Package: Date/time related
PHP Version: 4CVS, 5CVS (2004-03-11) OS: *
Private report: No CVE-ID:
 [2004-03-08 21:27 UTC] scottmacvicar at ntlworld dot com
Description:
------------
This bug seems to have different affect on Windows and Linux.

Windows
------
System has to be running GMT and Automatically adjust clock for daylight savings time checked.

You'll notice that the 27th appears twice. The second occurence of the 27th is Sat Mar 27 23:00:00 2004.
------

Redhat 9.0
------
The timestamp for linux on the 28th is Sun Mar 28 02:00:00 2004

/etc/sysconfig/clock
ZONE="Europe/London"
UTC=true
ARC=false
------
So Windows lost an hour and linux gained 2 hours.

Patch
--- datetime.c  2004-03-09 02:19:32.000000000 +0000
+++ datetime.c.patched  2004-03-09 02:20:48.000000000 +0000
@@ -192,8 +192,8 @@
                /* fall-through */ 
        case 1: /* hour */
                val = (*arguments[0])->value.lval; 
-               if (val < 1) { 
-                       chgsecs += (1-val) * 60*60; val = 1; 
+               if (val < 2) { 
+                       chgsecs += (2-val) * 60*60; val = 2; 
                } 
                ta->tm_hour = val; 
                /* fall-through */ 

Changing the time to
02:01:01 seems to correct this issue and the windows machine stops eating an hour and not setting tm_idst to 1 and i have no idea whats going on with the linux machine.

Reproduce code:
---------------
<?php
for ($i = 26; $i <= 29; $i++)
{
	$datestamp = gmmktime(0, 0, 0, 3, $i, 2004);
	$day = gmdate('j', $datestamp);
	echo "$datestamp - $day\n\n";
}
?>

Expected result:
----------------
1080259200 - 26
1080345600 - 27
1080432000 - 28
1080518400 - 29

Actual result:
--------------
Windows
---
1080259200 - 26
1080345600 - 27
1080428400 - 27
1080518400 - 29

Linux
---
1080259200 - 26
1080345600 - 27
1080439200 - 28
1080518400 - 29

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-03-09 09:41 UTC] webmaster at ragnarokonline dot de
wfm with my local timezone (Germany, GMT+1) but I could reproduce it, after I've changed the timzone to GMT+0 (Dublin, Edinburgh, Lissabon, London)

Autodetect DST-Settings was always active.
 [2004-03-09 09:44 UTC] webmaster at panyopanyo dot com
I too can confirm this occurs on my system which uses the clock settings described here
 [2004-03-12 12:10 UTC] rasmus@php.net
On my Linux box with TZ set to GMT I get:
1080259200 - 26
1080345600 - 27
1080432000 - 28
1080518400 - 29
which appears to me to be correct.  But if this patch works around the bug on Windows then I don't see any problem with it.  I don't see how it could negatively impact other platforms.
 [2004-03-12 12:23 UTC] rasmus@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 [2004-04-06 17:28 UTC] peter at rukavina dot net
The patch doesn't seem to have solved the problem.  Or perhaps it's introduced a new one?  Here's a simnple test case that calculates the GMT timestamp using gmmktime, then echos it back using gmstrftime, which should return the SAME time:

for ($day = 2 ; $day <= 6 ; $day++) {
    $datestamp = gmmktime(1,15,0,4,$day,2004);
    print gmstrftime("%Y-%m-%d %H:%M",$datestamp) . "\n";
}

Expected Result:
2004-04-02 01:15
2004-04-03 01:15
2004-04-04 01:15
2004-04-05 01:15
2004-04-06 01:15

Actual Result:
2004-04-02 01:15
2004-04-03 01:15
2004-04-04 03:15
2004-04-05 01:15
2004-04-06 01:15 

This only occurs when the datestamp is between 1:00 a.m. and 1:59 a.m. GMT on the day where DST takes effect.
 [2004-04-07 03:09 UTC] derick@php.net
It works fine for me, what operating system is this on? And in what timezone are you?

regards,
Derick
 [2004-04-07 09:38 UTC] peter at rukavina dot net
RedHat Enterprise Linux 3
Kernel 2.4.21-9.0.1.EL
PHP 4.3.5
 [2004-04-07 11:00 UTC] derick@php.net
Please answer all questions, and additionally: which glibc do you have?
 [2004-04-09 14:30 UTC] peter at nuvek dot com
I did some testing on a few machines I have here are the results

Broken:
#1
libc-2.3.2.so 
Linux version 2.4.22-28mdk (qateam@updates.mandrakesoft.com) (gcc version 3.3.1 (Mandrake Linux 9.2 3.3.1-2mdk)) #1 Thu Feb 19 22:28:14 MST 2004
PHP 5.0.0RC1 (cli) 
#2
libc-2.3.2.so 
Linux version 2.4.22 (root@(none)) (gcc version 3.3) #2 SMP Tue Feb 10 02:15:52 MST 2004
PHP 5.0.0RC1 (cli) 


Works:
#1
libc-2.3.2.so 
Linux version 2.4.22-28mdk (qateam@updates.mandrakesoft.com) (gcc version 3.3.1 (Mandrake Linux 9.2 3.3.1-2mdk)) #1 Thu Feb 19 22:28:14 MST 2004
PHP 4.3.4 (cli) 
#2
libc-2.2.4.so
Linux version 2.4.23 (root@(none)) (gcc version 2.95.3 20010315 (release)) #4 SMP Mon Dec 15 08:37:53 MST 2003
PHP 4.0.6


I hope this helps

Also of notem I have noticed that 
<?php
$date1 = mktime( 0, 0, 0, 4, 1, 2001 );
$date2 = mktime( 0, 0, 0, 4, 1, 2001 ) - 1;
print date("Y-m-d H:i:s",$date1)."\n";
print date("Y-m-d H:i:s",$date2)."\n";
?>

should produce:
2001-04-01 00:00:00
2001-03-31 23:59:59

But I get:
2001-04-01 01:00:00
2001-04-01 00:59:59

With the same sucess and failure as the above example
 [2004-04-09 15:15 UTC] derick@php.net
Works perfectly fine here with latest CVS versions of BOTH PHP 4 and PHP 5.
 [2004-04-09 18:51 UTC] peter at nuvek dot com
I just downloaded the CVS and it looks good.  Thanks.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Fri Apr 18 02:02:27 2014 UTC