From:             carstenklein at yahoo dot de
Operating system: Linux Ubuntu Feisty Fawn
PHP version:      5.2.4
PHP Bug Type:     Date/time related
Bug description:  getdate/mktime does not always add/subtract dst offset

Description:
------------
getdate() a/o mktime() do not always add/subtract the currently valid dst
offset. Actually, they do only add the dst offset under certain conditions,
but not always and not to all possible normal time/summer time, summer
time/normal time transitions.

see below code for an example on how to reprocude the erroneous behaviour.
the lines being marked with "good/failure" represent the lines where the
dst offset has been added. As you can see, it happens not for all possible
dates since 1970-1-1, at least in the local configuration being set to
CET/CEST.

BTW: opposed to what is expected, CEST to CET transitions do not seem to
work at all, I was unable to setup a scenario where the dst offset would
have been subtracted from the resulting timestamp. It seems as if the
mktime() or timelib functions do not take dst into account when
transitioning a date from summer time to normal time.

I would therefore like mktime and the timelib to no longer try to guess
the actual current time and automatically add the required dst offsets to
either date and time as it is prone to error as one can clearly see in the
below example outputs of below program fragment. Additionally, the results
often are non reproducible and may seem quite random. If you don't believe,
go and try for yourself, change the number of days to be added to the start
date from 20 to for example 10 or other reasonable values. Furthermore, try
to play with the starting date, make it some date in February instead of
for example March, but make sure that you transition the date beyond the
last Sunday in March, 1:00am. As you can see, the results will vary
greatly.

Of course one could always double check the results returned by mktime,
however, this is a lot of special casing etc. Therefore I urge you to at
least provide a timezone offset less version of mktime in order to at least
get some reproducible results.

And, using the seventh optional parameter to mktime() makes no difference
at all, besides that, it is considered deprecated.


similar bug reports, all having been closed so far:

http://bugs.php.net/bug.php?id=245
http://bugs.php.net/bug.php?id=741



Reproduce code:
---------------
<?php
function addDuration( $date, $durationArray ) {
        $t = getdate( $date ); $t[ "year" ] += $durationArray[ "years" ];
$t[ "mon" ] += $durationArray[ "months" ]; $t[ "mday" ] += $durationArray[
"days" ];
        $t[ "hours" ] += $durationArray[ "hours" ]; $t[ "minutes" ] +=
$durationArray[ "minutes" ]; $t[ "seconds" ] += $durationArray[ "seconds"
];
        return mktime( $t[ "hours" ], $t[ "minutes" ], $t[ "seconds" ],
$t[ "mon" ], $t[ "mday" ], $t[ "year" ] );
}
function durationToString( $durationArray ) {
        return "P" . $durationArray[ "years" ] . "Y" . $durationArray[
"months" ] . "M" . $durationArray[ "days" ] . "D" . "T" . $durationArray[
"hours" ] . ":" . $durationArray[ "minutes" ] . ":" . $durationArray[
"seconds" ];
}
echo "Testing Normal Time to DST Transition:\n";
for( $y = 1902; $y < 2038; $y++ ) {
        for( $x = 14; $x < 32; $x++ ) {
                $d = strtotime( "$y-03-$x 02:30:30" ); echo ( date( "Y-m-d
H:i:s", $d ) ) . "\t";
                $durationArray = array( "years" => 0, "months" => 0,
"days" => 20, "hours" => 0, "minutes" => 0, "seconds" => 0 ); echo "+\t" .
durationToString( $durationArray ) . "\t+\t";
                $t = addDuration( $d, $durationArray ); $td = getdate( $t
); echo date( "Y-m-d H:i:s", $t ) . ( $td[ "hours" ] == 3 ? "  <-  FAILURE"
: "" ) . "\n";
} }
echo "Testing DST to Normal Time Transition:\n";
for( $y = 2037; $y > 1901; $y-- ) {
        for( $x = 24; $x < 32; $x++ ) {
                $d = strtotime( "$y-10-$x 00:00:10" ); echo ( date( "Y-m-d
H:i:s", $d ) ) . "\t";
                $durationArray = array( "years" => 0, "months" => 0,
"days" => 1, "hours" => 0, "minutes" => 0, "seconds" => 0 ); echo "+\t" .
durationToString( $durationArray ) . "\t+\t";
                $t = addDuration( $d, $durationArray ); $td = getdate( $t
); echo date( "Y-m-d H:i:s", $t ) . ( $td[ "hours" ] == 23 ? "  <- 
FAILURE" : "" ) . "\n";
} }
?>


Expected result:
----------------
1981-03-25 02:30:30 + P0Y0M20DT0:0:0 + 1981-04-14 03:30:30
1981-03-26 02:30:30 + P0Y0M20DT0:0:0 + 1981-04-15 03:30:30
1981-03-27 02:30:30 + P0Y0M20DT0:0:0 + 1981-04-16 03:30:30
1981-03-28 02:30:30 + P0Y0M20DT0:0:0 + 1981-04-17 03:30:30
1981-03-29 03:30:30 + P0Y0M20DT0:0:0 + 1981-04-18 03:30:30  <-  FAILURE
1981-03-30 02:30:30 + P0Y0M20DT0:0:0 + 1981-04-19 02:30:30
1981-03-31 02:30:30 + P0Y0M20DT0:0:0 + 1981-04-20 02:30:30
1982-03-14 02:30:30 + P0Y0M20DT0:0:0 + 1982-04-03 02:30:30
1982-03-15 02:30:30 + P0Y0M20DT0:0:0 + 1982-04-04 02:30:30
1982-03-16 02:30:30 + P0Y0M20DT0:0:0 + 1982-04-05 02:30:30
1982-03-17 02:30:30 + P0Y0M20DT0:0:0 + 1982-04-06 02:30:30

* what is marked failure is actually the last sunday in march, 1981


Actual result:
--------------
1981-03-25 02:30:30 + P0Y0M20DT0:0:0 + 1981-04-14 02:30:30
1981-03-26 02:30:30 + P0Y0M20DT0:0:0 + 1981-04-15 02:30:30
1981-03-27 02:30:30 + P0Y0M20DT0:0:0 + 1981-04-16 02:30:30
1981-03-28 02:30:30 + P0Y0M20DT0:0:0 + 1981-04-17 02:30:30
1981-03-29 03:30:30 + P0Y0M20DT0:0:0 + 1981-04-18 03:30:30  <-  FAILURE
1981-03-30 02:30:30 + P0Y0M20DT0:0:0 + 1981-04-19 02:30:30
1981-03-31 02:30:30 + P0Y0M20DT0:0:0 + 1981-04-20 02:30:30
1982-03-14 02:30:30 + P0Y0M20DT0:0:0 + 1982-04-03 02:30:30
1982-03-15 02:30:30 + P0Y0M20DT0:0:0 + 1982-04-04 02:30:30
1982-03-16 02:30:30 + P0Y0M20DT0:0:0 + 1982-04-05 02:30:30
1982-03-17 02:30:30 + P0Y0M20DT0:0:0 + 1982-04-06 02:30:30

*) what is marked as FAILURE is actually correct, however,
all the other dates before also transition from non-dst to dst,
in the local configuration, i.e. CET to CEST, so these
should also have a local time reading of 03:30:30 instead
of just 02:30:30.

-- 
Edit bug report at http://bugs.php.net/?id=42645&edit=1
-- 
Try a CVS snapshot (PHP 4.4): 
http://bugs.php.net/fix.php?id=42645&r=trysnapshot44
Try a CVS snapshot (PHP 5.2): 
http://bugs.php.net/fix.php?id=42645&r=trysnapshot52
Try a CVS snapshot (PHP 6.0): 
http://bugs.php.net/fix.php?id=42645&r=trysnapshot60
Fixed in CVS:                 http://bugs.php.net/fix.php?id=42645&r=fixedcvs
Fixed in release:             
http://bugs.php.net/fix.php?id=42645&r=alreadyfixed
Need backtrace:               http://bugs.php.net/fix.php?id=42645&r=needtrace
Need Reproduce Script:        http://bugs.php.net/fix.php?id=42645&r=needscript
Try newer version:            http://bugs.php.net/fix.php?id=42645&r=oldversion
Not developer issue:          http://bugs.php.net/fix.php?id=42645&r=support
Expected behavior:            http://bugs.php.net/fix.php?id=42645&r=notwrong
Not enough info:              
http://bugs.php.net/fix.php?id=42645&r=notenoughinfo
Submitted twice:              
http://bugs.php.net/fix.php?id=42645&r=submittedtwice
register_globals:             http://bugs.php.net/fix.php?id=42645&r=globals
PHP 3 support discontinued:   http://bugs.php.net/fix.php?id=42645&r=php3
Daylight Savings:             http://bugs.php.net/fix.php?id=42645&r=dst
IIS Stability:                http://bugs.php.net/fix.php?id=42645&r=isapi
Install GNU Sed:              http://bugs.php.net/fix.php?id=42645&r=gnused
Floating point limitations:   http://bugs.php.net/fix.php?id=42645&r=float
No Zend Extensions:           http://bugs.php.net/fix.php?id=42645&r=nozend
MySQL Configuration Error:    http://bugs.php.net/fix.php?id=42645&r=mysqlcfg

Reply via email to