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