ID: 20382
Updated by: [EMAIL PROTECTED]
Reported By: [EMAIL PROTECTED]
-Status: Feedback
+Status: Open
Bug Type: Date/time related
Operating System: Linux Mandrake 7.2
PHP Version: 4.3.0-dev
Previous Comments:
------------------------------------------------------------------------
[2002-11-21 23:42:22] [EMAIL PROTECTED]
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.
------------------------------------------------------------------------
[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