Thanks,  I added the comment, and the 4.3.2 patch to the bug report.
Luke

On Mon, Aug 18, 2003 at 04:55:56PM -0500, Luke Ehresman wrote:
> Hi,
> 
> A co-worker and I have been working on some intensive timestamp/timezone
> manipulation code for the past week or so, and ran across what we believed
> to be a bug in the way PHP handled gmmktime().  Browsing through the code,
> sure enough I found the source of the problem.  I fixed it, and have
> attached a patch.
> 
> As I was searching around, I discovered that this has been an open bug
> since 4.0.6 (2 years!).  I believe that this patch should fix most of the
> issues related to the following problem:
>     http://bugs.php.net/bug.php?id=14391
> 
> 
> The Problem:
> ============
> The function gmmktime() is supposed to take a date in GMT as a paramter
> and return a timestamp in GMT.  No manipulation of the time should occur.
> The only circumstance in which manipulation of the time should happen is
> if the seventh parameter (is_dst) is set to 1.  This is the expected
> behavior.  However, in reality I noticed that when I didn't specify a
> seventh parameter, it was applying a daylight savings time offset when I
> tried to get the epoch.  See the example code.
> 
> <?php
> 
>     // Get a timestamp for the epoch (jan 1, 1970)
>     echo "<pre>";
>     echo gmmktime(0,0,0,1,1,1970,1)."\n";
>     echo gmmktime(0,0,0,1,1,1970,0)."\n";
>     echo gmmktime(0,0,0,1,1,1970)."\n";
> 
>     // Now get timestamp for June 1
>     echo "\n";
>     echo gmmktime(0,0,0,6,1,1970,1)."\n";
>     echo gmmktime(0,0,0,6,1,1970,0)."\n";
>     echo gmmktime(0,0,0,6,1,1970)."\n";
> 
> ?>
> 
> I expected the first set of outputs to look like this:
> 
>     -3600
>     0
>     0
> 
> Which it does, so this is fine.  However, The second block of outputs is
> in June which if I had been using simply mktime(), I would have expected a
> DST offset (note: DST = daylight savings time) to be applied by default
> (on the 3rd command).  However, since I'm using gmmktime() by default no
> DST offset should be applied.  The odd behavior manifests itself in the
> second block of output:
> 
>     13046400
>     13050000
>     13046400
> 
> This is pretty meaningless until you realize what is actually going on.
> The last output, which is generated by a gmmktime() that has no 7th
> parameter, is applying an offset for daylight savings time.
> 
> The Solution
> ============
> I had a moment of panic and was sincerely hoping that GMT did not actually
> use daylight savings time, so I did some research and found that while the
> timezone that contains Greenwich actually does use daylight savings time,
> the GMT standard time reference does not.  So right there I knew something
> was wrong on the PHP side.  I loaded up the source of PHP (like a good
> open source enthusiast), and sure enough, I discovered the source of the
> problem (no pun intended).
> 
> PHP is using the C function php_mktime() for both mktime() and gmmktime().
> There is a flag as a parameter called "gm" which is 1 or 0 depending on
> whether it was called from mktime() or gmmktime().  The problem is that
> there is no check before applying the server's daylight savings
> information to the timestamp.
> 
> As a fix for this, I changed the behavior so that by default if there is
> no 7th parameter for gmmktime, it will not apply any DST offset.  This
> differs from mktime which by default will appy the server's DST offset.
> 
> I have attached patches for both PHP php-5.0.0b1 and php-4.3.2.  I would
> imagine the same code would work on most recent versions of PHP as it
> doesn't seem that this function has had much recent development.  The
> patch can be applied by using the following:
> 
>     $ cd /usr/local/php-4.3.2
>     $ patch -p2 < ~/gmmktime-php_4.3.2.patch
> 
> Feel free to contact me if you have any questions.
> 
> Luke
> -- 
> Luke Ehresman
> luke[at]ehresman.org
> http://www.luke.ehresman.org

> diff -u clean/php-4.3.2/ext/standard/datetime.c php-4.3.2/ext/standard/datetime.c
> --- clean/php-4.3.2/ext/standard/datetime.c   2003-05-04 07:22:00.000000000 -0400
> +++ php-4.3.2/ext/standard/datetime.c 2003-08-18 17:18:19.000000000 -0400
> @@ -116,7 +116,20 @@
>       /* Let DST be unknown. mktime() should compute the right value
>       ** and behave correctly. Unless the user overrides this.
>       */
> -     ta->tm_isdst = -1;
> +     /*
> +     **  If we are using gmmktime(), do not use the local
> +     **  server's setting of DST.  GMT does not use daylight
> +     **  savings, so unless the user overrides us, this should
> +     **  be set to 0.
> +     **  - Luke Ehresman, Aug 2003, <[EMAIL PROTECTED]>
> +     */
> +     if (gm) {
> +             ta->tm_isdst = 0;
> +             is_dst = 0;
> +     } else {
> +             ta->tm_isdst = -1;
> +             is_dst = -1;
> +     }
>  
>       /*
>       ** Now change date values with supplied parameters.
> Common subdirectories: clean/php-4.3.2/ext/standard/tests and 
> php-4.3.2/ext/standard/tests

> --- php-5.0.0b1/ext/standard/bak      2003-08-18 17:30:31.000000000 -0400
> +++ php-5.0.0b1/ext/standard/datetime.c       2003-08-18 17:30:48.000000000 -0400
> @@ -112,7 +112,20 @@
>       /* Let DST be unknown. mktime() should compute the right value
>       ** and behave correctly. Unless the user overrides this.
>       */
> -     ta->tm_isdst = -1;
> +     /*
> +     **  If we are using gmmktime(), do not use the local
> +     **  server's setting of DST.  GMT does not use daylight
> +     **  savings, so unless the user overrides us, this should
> +     **  be set to 0.
> +     **  - Luke Ehresman, Aug 2003, <[EMAIL PROTECTED]>
> +     */
> +     if (gm) {
> +             ta->tm_isdst = 0;
> +             is_dst = 0;
> +     } else {
> +             ta->tm_isdst = -1;
> +             is_dst = -1;
> +     }
>  
>       /*
>       ** Now change date values with supplied parameters.
> 

> -- 
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php

-- 
Luke Ehresman
luke[at]ehresman.org
http://www.luke.ehresman.org

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to