From: Rasmus Lerdorf Date: Sun, 28 Mar 2004 15:03:56 +0000 (+0000) Subject: MFB test case for bug #27719 and improve comments in this tricky DST code X-Git-Tag: php-5.0.0RC2RC1~186 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1ece5eb5ad11613f6b637dee4901c7dd7c6abc3d;p=php MFB test case for bug #27719 and improve comments in this tricky DST code --- diff --git a/NEWS b/NEWS index 399bf2e278..84c841b08f 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ????? 2004, PHP 5 Release Candidate 2 +- Fixed bug #27719 (mktime issues on and around DST changeover). (Rasmus) - Changed sqlite to use studlyCaps convention for its OO API. (Marcus) - Force destructors to have empty signatures. (Marcus) - Stopped file uploads from throwing E_WARNINGs and E_NOTICEs which can not be diff --git a/ext/standard/datetime.c b/ext/standard/datetime.c index fe973c8042..b639c37a2f 100644 --- a/ext/standard/datetime.c +++ b/ext/standard/datetime.c @@ -158,7 +158,7 @@ void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gm) ta->tm_year = Z_LVAL_PP(arguments[5]) - ((Z_LVAL_PP(arguments[5]) > 1000) ? 1900 : 0); /* fall-through */ - case 5: /* day in month (1-baesd) */ + case 5: /* day in month (1-based) */ val = (*arguments[4])->value.lval; if (val < 1) { chgsecs += (1-val) * 60*60*24; @@ -190,10 +190,10 @@ void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gm) case 1: /* hour */ val = (*arguments[0])->value.lval; /* - We don't use 1 here to work around problems in some mktime implementations - when it comes to daylight savings time. Setting it to 4 and working back from - there with the chgsecs offset makes us immune to these problems. - See http://bugs.php.net/27533 for more info. + We avoid midnight and a couple of hours after midnight here to work around + various OS-level bugs in mktime and specifically daylight savings time issues + in many mktime implementation. + See bugs #27533 and #27719 for more info. */ if (val < 4) { chgsecs += (4-val) * 60*60; val = 4; @@ -215,6 +215,11 @@ void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gm) seconds = t - chgsecs; + /* + Here we check to see if the chgsecs fuzz factor we applied caused us to + move from dst to non-dst or vice-versa. If so we adjust accordingly to + avoid being off by an hour on the dst changeover date. + */ if (is_dst == -1) { struct tm t1, t2; t1 = *localtime(&t); @@ -225,6 +230,11 @@ void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gm) ta = localtime(&seconds); } + /* + If the user didn't specify whether the timestamp passed in was dst or not + then we fill it in based on the dst setting at the evaluated timestamp + at the current TZ + */ is_dst = ta->tm_isdst; } diff --git a/ext/standard/tests/time/bug27719.phpt b/ext/standard/tests/time/bug27719.phpt new file mode 100644 index 0000000000..926fc582e2 --- /dev/null +++ b/ext/standard/tests/time/bug27719.phpt @@ -0,0 +1,65 @@ +--TEST-- +Bug #27719: mktime returns incorrect timestamp for dst days +--FILE-- + +--EXPECT-- +1081054800 04/04/04 12:00:00 +1081054800 04/04/04 12:00:00 +1081054800 04/04/04 12:00:00 + +1075870800 02/04/04 12:00:00 +1075867200 02/03/04 11:00:00 +1075870800 02/04/04 12:00:00 + +1081054800 04/04/04 12:00:00 +1081051200 04/03/04 11:00:00 +1081054800 04/04/04 12:00:00 + +1081065600 04/04/04 04:00:00 +1081062000 04/04/04 03:00:00 +1081062000 04/04/04 03:00:00 + +1086325200 06/04/04 01:00:00 +1086321600 06/04/04 12:00:00 +1086321600 06/04/04 12:00:00