Re: PHP 4.0.1
| From: | Andrei Zmievski | Date: | Tue, 13 Jun 2000 04:29:42 +0000 |
| Subject: | Re: PHP 4.0.1 | ||
| References: | 1 2 3 4 | Groups: | php.dev |
| Request: | Send a blank email to php-dev+get-21176@lists.php.net to get a copy of this message | ||
On Mon, 12 Jun 2000, Andi Gutmans wrote:
> I agree unless it takes a year to fix :)
> Let's wait and see how your patch comes out.
Here it is and some test code.
Basically, I noticed the error when I wanted to take a GMT date/time and
convert it to local time. Before the patch the output of the code below
was totally wrong - it did not account for non-HAVE_TM_GMTOFF case where
timezone offsets are positive instead of negative, like in
HAVE_TM_GMTOFF case. Furthermore, it didn't seem to do daylight savings
time adjustment correctly. With the patch the following code:
<?
var_dump(date("M d, Y H:i:s", gmmktime(12, 0, 0, 6, 9, 2000)));
var_dump(date("M d, Y H:i:s", gmmktime(12, 0, 0, 6, 9, 2000, 1)));
var_dump(date("M d, Y H:i:s", gmmktime(12, 0, 0, 6, 9, 2000, 0)));
?>
gives:
string(21) "Jun 09, 2000 07:00:00"
string(21) "Jun 09, 2000 07:00:00"
string(21) "Jun 09, 2000 06:00:00"
Which is exactly what I'd expect for noon GMT time for my timezone (CDT
= -0500).
So, I propose the attached patch. Please review and comment.
-Andrei
"The time from now until the completion
of the project tends to become constant." -- Douglas Hartree
Index: ext/standard/datetime.c =================================================================== RCS file: /repository/php4/ext/standard/datetime.c,v retrieving revision 1.43 diff -u -r1.43 datetime.c --- ext/standard/datetime.c 2000/06/09 20:18:36 1.43 +++ ext/standard/datetime.c 2000/06/12 20:08:14 @@ -53,7 +53,7 @@ }; #if !defined(HAVE_TM_ZONE) && !defined(_TIMEZONE) && !defined(HAVE_DECLARED_TIMEZONE) -extern time_t timezone; +extern time_t timezone, altzone; extern int daylight; #endif @@ -81,6 +81,7 @@ struct tm *ta, tmbuf; time_t t; int i, gmadjust, seconds, arg_count = ZEND_NUM_ARGS(); + int is_dst = -1; if (arg_count > 7 || zend_get_parameters_array_ex(arg_count,arguments) == FAILURE) { WRONG_PARAM_COUNT; @@ -116,7 +117,7 @@ */ switch(arg_count) { case 7: - ta->tm_isdst = (*arguments[6])->value.lval; + ta->tm_isdst = is_dst = (*arguments[6])->value.lval; /* fall-through */ case 6: /* @@ -155,6 +156,8 @@ } seconds = mktime(ta); + if (is_dst == -1) + is_dst = ta->tm_isdst; if (gm) { #if HAVE_TM_GMTOFF @@ -165,11 +168,12 @@ gmadjust = ta->tm_gmtoff; #else /* - ** Without tm_gmtoff, the non-ANSI C run-time global 'timezone' - ** variable simply returns the current Winter GMT offset - ** in the current locale (defined in DOS/Windows compilers). + ** If correcting for daylight savings time, we set the adjustment to + ** the value of altzone variable. Otherwise, we need to overcorrect and + ** set the adjustment to the main timezone offset plus difference + ** between the main and alternate ones. */ - gmadjust = timezone; + gmadjust = -(is_dst ? altzone : timezone + (timezone - altzone)); #endif seconds += gmadjust; } @@ -405,9 +409,9 @@ break; case 'Z': /* timezone offset in seconds */ #if HAVE_TM_GMTOFF - sprintf(tmp_buff, "%ld", ta->tm_isdst ? ta->tm_gmtoff-3600 : ta->tm_gmtoff); + sprintf(tmp_buff, "%ld", ta->tm_gmtoff); #else - sprintf(tmp_buff, "%ld", daylight ? timezone-3600 : timezone); + sprintf(tmp_buff, "%ld", ta->tm_isdst ? altzone : timezone); #endif strcat(return_value->value.str.val, tmp_buff); break; @@ -720,8 +724,8 @@ RETURN_LONG(parsedate((*timep)->value.str.val, NULL)); } } - /* }}} */ + /* * Local variables:
Index: ext/standard/datetime.c =================================================================== RCS file: /repository/php4/ext/standard/datetime.c,v retrieving revision 1.43 diff -u -r1.43 datetime.c --- ext/standard/datetime.c 2000/06/09 20:18:36 1.43 +++ ext/standard/datetime.c 2000/06/12 20:08:14 @@ -53,7 +53,7 @@ }; #if !defined(HAVE_TM_ZONE) && !defined(_TIMEZONE) && !defined(HAVE_DECLARED_TIMEZONE) -extern time_t timezone; +extern time_t timezone, altzone; extern int daylight; #endif @@ -81,6 +81,7 @@ struct tm *ta, tmbuf; time_t t; int i, gmadjust, seconds, arg_count = ZEND_NUM_ARGS(); + int is_dst = -1; if (arg_count > 7 || zend_get_parameters_array_ex(arg_count,arguments) == FAILURE) { WRONG_PARAM_COUNT; @@ -116,7 +117,7 @@ */ switch(arg_count) { case 7: - ta->tm_isdst = (*arguments[6])->value.lval; + ta->tm_isdst = is_dst = (*arguments[6])->value.lval; /* fall-through */ case 6: /* @@ -155,6 +156,8 @@ } seconds = mktime(ta); + if (is_dst == -1) + is_dst = ta->tm_isdst; if (gm) { #if HAVE_TM_GMTOFF @@ -165,11 +168,12 @@ gmadjust = ta->tm_gmtoff; #else /* - ** Without tm_gmtoff, the non-ANSI C run-time global 'timezone' - ** variable simply returns the current Winter GMT offset - ** in the current locale (defined in DOS/Windows compilers). + ** If correcting for daylight savings time, we set the adjustment to + ** the value of altzone variable. Otherwise, we need to overcorrect and + ** set the adjustment to the main timezone offset plus difference + ** between the main and alternate ones. */ - gmadjust = timezone; + gmadjust = -(is_dst ? altzone : timezone + (timezone - altzone)); #endif seconds += gmadjust; } @@ -405,9 +409,9 @@ break; case 'Z': /* timezone offset in seconds */ #if HAVE_TM_GMTOFF - sprintf(tmp_buff, "%ld", ta->tm_isdst ? ta->tm_gmtoff-3600 : ta->tm_gmtoff); + sprintf(tmp_buff, "%ld", ta->tm_gmtoff); #else - sprintf(tmp_buff, "%ld", daylight ? timezone-3600 : timezone); + sprintf(tmp_buff, "%ld", ta->tm_isdst ? altzone : timezone); #endif strcat(return_value->value.str.val, tmp_buff); break; @@ -720,8 +724,8 @@ RETURN_LONG(parsedate((*timep)->value.str.val, NULL)); } } - /* }}} */ + /* * Local variables: