ID: 20382 Comment by: [EMAIL PROTECTED] Reported By: [EMAIL PROTECTED] Status: Feedback Bug Type: Date/time related Operating System: Linux Mandrake 7.2 PHP Version: 4.3.0-dev New Comment:
Ran the automated-date-test script on a different box, this one running windows 2000 SP2 (previously was Mandrake Linux 7.2), using the latest available snapshot of the 4.4.0-dev tree (was php4-win32-200211220330), and it produced the same list of incorrect dates as in the above comment. Previous Comments: ------------------------------------------------------------------------ [2002-11-12 19:46:28] [EMAIL PROTECTED] OK, I decided that was needed was some kind of automated testing, so I wrote it: ============================================ #!/root/php4-200211122230 -q <?php // report any errors at all error_reporting (E_ALL); // pass a date, supply a strtotime modifier, and get a date back function getDateWithModifier($date, $modifier) { list ($year, $month, $day) = explode ("-",$date); $starting_timestamp = mktime (1,1,1,$month,$day,$year); $timestamp_with_modifier = strtotime ($modifier, $starting_timestamp); return date("Y-n-j", $timestamp_with_modifier); } /* ** @desc: for the specified date, will find the date for the desired day of the ** week that is also in the same week. Does NOT use 'strtotime' */ function getDayOfTheWeekFromDate($date, $desired_day_of_week) { // weekdays - note special case for sundays (7, not 0), so as to treat as end of week, not start $weekdays = array ("Sunday" => 7, "Monday" => 1, "Tuesday" => 2, "Wednesday" => 3, "Thursday" => 4, "Friday" => 5, "Saturday" => 6); // convert into a number $desired_day_of_week_number = $weekdays[$desired_day_of_week]; // see what day we have currently list ($year, $month, $day) = explode ("-",$date); $date_day_of_week = date("w", mktime (17,17,17,$month,$day,$year)); $new_day = $day+(($desired_day_of_week_number-$date_day_of_week)+7) % 7; return date("Y-n-j", mktime (17,17,17,$month,$new_day,$year)); } // run an automated test to compare the output of these two functions, and complain if they differ for ($i=1; $i<1000; $i++) { $date = date("Y-n-j", mktime (17,17,17,1,$i,1999)); $strtotime_date = getDateWithModifier($date, "Monday"); $other_date = getDayOfTheWeekFromDate($date, "Monday"); if ($strtotime_date != $other_date) { print "Discrepancy for $date - results were $strtotime_date vs $other_date\n"; } } print "PHP version: " . phpversion(). "<br>\n"; ?> ============================================ Here's the output that I get: ============================================ [root@www tmp]# ./automated-date-test.php Discrepancy for 1999-3-23 - results were 1999-3-28 vs 1999-3-29 Discrepancy for 1999-3-24 - results were 1999-3-28 vs 1999-3-29 Discrepancy for 1999-3-25 - results were 1999-3-28 vs 1999-3-29 Discrepancy for 1999-3-26 - results were 1999-3-28 vs 1999-3-29 Discrepancy for 1999-3-27 - results were 1999-3-28 vs 1999-3-29 Discrepancy for 1999-3-28 - results were 1999-3-28 vs 1999-3-29 Discrepancy for 2000-3-21 - results were 2000-3-26 vs 2000-3-27 Discrepancy for 2000-3-22 - results were 2000-3-26 vs 2000-3-27 Discrepancy for 2000-3-23 - results were 2000-3-26 vs 2000-3-27 Discrepancy for 2000-3-24 - results were 2000-3-26 vs 2000-3-27 Discrepancy for 2000-3-25 - results were 2000-3-26 vs 2000-3-27 Discrepancy for 2000-3-26 - results were 2000-3-26 vs 2000-3-27 Discrepancy for 2001-3-20 - results were 2001-3-25 vs 2001-3-26 Discrepancy for 2001-3-21 - results were 2001-3-25 vs 2001-3-26 Discrepancy for 2001-3-22 - results were 2001-3-25 vs 2001-3-26 Discrepancy for 2001-3-23 - results were 2001-3-25 vs 2001-3-26 Discrepancy for 2001-3-24 - results were 2001-3-25 vs 2001-3-26 Discrepancy for 2001-3-25 - results were 2001-3-25 vs 2001-3-26 PHP version: 4.3.0-dev<br> [root@www tmp]# ============================================ In other words, the result for these 6 days of the year consistently appears to be wrong. (I suppose I should be glad that the very first date I choose to test this function with just by fluke happened to be one of those 6 days, as opposed to causing mysterious problems later!) Does anyone else get any results that appear incorrect on running this script? ------------------------------------------------------------------------ [2002-11-12 19:25:41] [EMAIL PROTECTED] No problem - Modified script slightly, as shown below, to use gmmktime(), and to also print out the before and after timestamps. Source: ========================================= #!/root/php4-200211122230 -q <?php // report any errors at all error_reporting (E_ALL); // pass a date, supply a strtotime modifier, and get a date back function getDateWithModifier($date, $modifier) { list ($year, $month, $day) = explode ("-",$date); $t_start = gmmktime (17,17,17,$month,$day,$year); $t_new = strtotime ($modifier, $t_start); return "t_start: $t_start; t_new: $t_new; " . date("Y-n-j", $t_new); } print "<hr>\n"; print "2001-3-17, goto mon: " . getDateWithModifier("2001-3-17", "Monday") . "; should be 2001-3-19.<br>\n"; print "2001-3-18, goto mon: " . getDateWithModifier("2001-3-18", "Monday") . "; should be 2001-3-19.<br>\n"; print "2001-3-19, goto mon: " . getDateWithModifier("2001-3-19", "Monday") . "; should be 2001-3-19.<br>\n"; print "2001-3-20, goto mon: " . getDateWithModifier("2001-3-20", "Monday") . "; should be 2001-3-26 ###.<br>\n"; print "2001-3-21, goto mon: " . getDateWithModifier("2001-3-21", "Monday") . "; should be 2001-3-26 ###.<br>\n"; print "2001-3-22, goto mon: " . getDateWithModifier("2001-3-22", "Monday") . "; should be 2001-3-26 ###.<br>\n"; print "2001-3-23, goto mon: " . getDateWithModifier("2001-3-23", "Monday") . "; should be 2001-3-26 ###.<br>\n"; print "2001-3-24, goto mon: " . getDateWithModifier("2001-3-24", "Monday") . "; should be 2001-3-26 ###.<br>\n"; print "2001-3-25, goto mon: " . getDateWithModifier("2001-3-25", "Monday") . "; should be 2001-3-26 ###.<br>\n"; print "2001-3-26, goto mon: " . getDateWithModifier("2001-3-26", "Monday") . "; should be 2001-3-26.<br>\n"; print "2001-3-27, goto mon: " . getDateWithModifier("2001-3-27", "Monday") . " ; should be 2001-4-2.<br>\n"; print "<hr>\n"; print "PHP version: " . phpversion(). "<br>\n"; ?> ========================================= Output: ========================================== [root@www tmp]# ./script.php <hr> 2001-3-17, goto mon: t_start: 984849437; t_new: 984920400; 2001-3-19; should be 2001-3-19.<br> 2001-3-18, goto mon: t_start: 984935837; t_new: 984920400; 2001-3-19; should be 2001-3-19.<br> 2001-3-19, goto mon: t_start: 985022237; t_new: 985525200; 2001-3-25; should be 2001-3-19.<br> 2001-3-20, goto mon: t_start: 985108637; t_new: 985525200; 2001-3-25; should be 2001-3-26 ###.<br> 2001-3-21, goto mon: t_start: 985195037; t_new: 985525200; 2001-3-25; should be 2001-3-26 ###.<br> 2001-3-22, goto mon: t_start: 985281437; t_new: 985525200; 2001-3-25; should be 2001-3-26 ###.<br> 2001-3-23, goto mon: t_start: 985367837; t_new: 985525200; 2001-3-25; should be 2001-3-26 ###.<br> 2001-3-24, goto mon: t_start: 985454237; t_new: 985525200; 2001-3-25; should be 2001-3-26 ###.<br> 2001-3-25, goto mon: t_start: 985540637; t_new: 985528800; 2001-3-26; should be 2001-3-26 ###.<br> 2001-3-26, goto mon: t_start: 985627037; t_new: 986133600; 2001-4-2; should be 2001-3-26.<br> 2001-3-27, goto mon: t_start: 985713437; t_new: 986133600; 2001-4-2 ; should be 2001-4-2.<br> <hr> PHP version: 4.3.0-dev<br> [root@www tmp]# ========================================== And here is the output using mktime() instead of gmmktime(): ========================================== [root@www tmp]# ./script.php <hr> 2001-3-17, goto mon: t_start: 984809837; t_new: 984920400; 2001-3-19; should be 2001-3-19.<br> 2001-3-18, goto mon: t_start: 984896237; t_new: 984920400; 2001-3-19; should be 2001-3-19.<br> 2001-3-19, goto mon: t_start: 984982637; t_new: 984920400; 2001-3-19; should be 2001-3-19.<br> 2001-3-20, goto mon: t_start: 985069037; t_new: 985525200; 2001-3-25; should be 2001-3-26 ###.<br> 2001-3-21, goto mon: t_start: 985155437; t_new: 985525200; 2001-3-25; should be 2001-3-26 ###.<br> 2001-3-22, goto mon: t_start: 985241837; t_new: 985525200; 2001-3-25; should be 2001-3-26 ###.<br> 2001-3-23, goto mon: t_start: 985328237; t_new: 985525200; 2001-3-25; should be 2001-3-26 ###.<br> 2001-3-24, goto mon: t_start: 985414637; t_new: 985525200; 2001-3-25; should be 2001-3-26 ###.<br> 2001-3-25, goto mon: t_start: 985504637; t_new: 985525200; 2001-3-25; should be 2001-3-26 ###.<br> 2001-3-26, goto mon: t_start: 985591037; t_new: 985528800; 2001-3-26; should be 2001-3-26.<br> 2001-3-27, goto mon: t_start: 985677437; t_new: 986133600; 2001-4-2 ; should be 2001-4-2.<br> <hr> PHP version: 4.3.0-dev<br> [root@www tmp]# ========================================== ------------------------------------------------------------------------ [2002-11-12 18:46:02] [EMAIL PROTECTED] Hmm..could you try changing that mktime() to gmmktime() ? And also add output of the gm/mktime() only to see what you get as timestamp. ------------------------------------------------------------------------ [2002-11-12 18:10:27] [EMAIL PROTECTED] Happy to comply. I tried it with the CVS snapshot (php4-200211122230), output was: ============================================================= [root@www tmp]# ./script.php <hr> from 2001-3-17, goto monday: 2001-3-19; should be 2001-3-19.<br> from 2001-3-18, goto monday: 2001-3-19; should be 2001-3-19.<br> from 2001-3-19, goto monday: 2001-3-19; should be 2001-3-19.<br> from 2001-3-20, goto monday: 2001-3-25; should be 2001-3-26 ###.<br> from 2001-3-21, goto monday: 2001-3-25; should be 2001-3-26 ###.<br> from 2001-3-22, goto monday: 2001-3-25; should be 2001-3-26 ###.<br> from 2001-3-23, goto monday: 2001-3-25; should be 2001-3-26 ###.<br> from 2001-3-24, goto monday: 2001-3-25; should be 2001-3-26 ###.<br> from 2001-3-25, goto monday: 2001-3-25; should be 2001-3-26 ###.<br> from 2001-3-26, goto monday: 2001-3-26; should be 2001-3-26.<br> from 2001-3-27, goto monday: 2001-4-2 ; should be 2001-4-2.<br> <hr> PHP version: 4.3.0-dev<br> [root@www tmp]# ============================================================= i.e. same problem. The location of the php command-line executable appears to have changed to 'sapi/cli/php' (in the PHP 4.2.3 build process the executable just ends up in the root of the source directory), so this was what I used, hope this is OK. Here is some more info related to the problem that may or may not be relevant: * This machine and I are located in Sydney, Australia. The machine's timezone as shown in 'timeconfig' is set of "Australia/Sydney", and "Hardware clock set to GMT" is shown turned off. Output of the 'date' command looks like this: "Wed Nov 13 10:40:22 EST 2002". Sydney is (depending on daylight savings) around GMT + 10 hours. * I've found today that there was a daylight savings transition for this timezone in that week. From: http://www.dstc.qut.edu.au/DST/marg/daylight.html - "[Daylight savings] ends at 3am on Sunday 25 March 2001. Clocks should be turned back one hour to read 2am (Australian Eastern Standard Time)." * Since there was a daylight savings transition, I've now tried various parameters to the 'mktime' line, in case the hour/minute/second parameters chosen were causing problems because they were too close to the time transition. I've tried the following parameters, all of which produce the same incorrect result: - mktime (23,23,23,$month,$day,$year); - mktime (15,15,15,$month,$day,$year); - mktime (10,10,10,$month,$day,$year); - mktime (5,5,5,$month,$day,$year); - mktime (1,1,1,$month,$day,$year); ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at http://bugs.php.net/20382 -- Edit this bug report at http://bugs.php.net/?id=20382&edit=1