summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRasmus Lerdorf <rasmus@php.net>2004-03-28 14:57:32 +0000
committerRasmus Lerdorf <rasmus@php.net>2004-03-28 14:57:32 +0000
commit885e837b2a141ad7097bebe2cc1464fdac304745 (patch)
tree170404427204c994944a7eca60399bb1d351f3e6
parent6a3fc10b05d0c5a5d2da123f2f0b61ea774fb1b9 (diff)
downloadphp-git-885e837b2a141ad7097bebe2cc1464fdac304745.tar.gz
- Merge whitespace and trivial changes from HEAD back to the branch so the
diff between HEAD and PHP_4_3 only shows feature changes - Fix test case for bug #27719 (TZ=EST means no DST so the test was wrong)
-rw-r--r--NEWS1
-rw-r--r--ext/session/session.c2
-rw-r--r--ext/standard/datetime.c83
-rw-r--r--ext/standard/head.c4
-rw-r--r--ext/standard/tests/time/bug27719.phpt67
5 files changed, 108 insertions, 49 deletions
diff --git a/NEWS b/NEWS
index 1641156095..a11481b249 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,7 @@
PHP 4 NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 2004, Version 4.3.6
+- Fixed bug #27719 (mktime issues on and around DST changeover). (Rasmus)
- Fixed bug #27717 (Test Failures when compiled on 64-bit mode). (Ard, Derick)
- Fixed bug #27687 (Bug Adding Default Charset to 'text/*' Content-Type
Header). (Marcus)
diff --git a/ext/session/session.c b/ext/session/session.c
index bf4c495382..2356290c9a 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -863,7 +863,7 @@ static void php_session_send_cookie(TSRMLS_D)
t = tv.tv_sec + PS(cookie_lifetime);
if (t > 0) {
- date_fmt = php_std_date(t);
+ date_fmt = php_std_date(t TSRMLS_CC);
smart_str_appends(&ncookie, COOKIE_EXPIRES);
smart_str_appends(&ncookie, date_fmt);
efree(date_fmt);
diff --git a/ext/standard/datetime.c b/ext/standard/datetime.c
index 43017881b0..cee60d092a 100644
--- a/ext/standard/datetime.c
+++ b/ext/standard/datetime.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2003 The PHP Group |
+ | Copyright (c) 1997-2004 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 2.02 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -18,10 +18,8 @@
+----------------------------------------------------------------------+
*/
-
/* $Id$ */
-
#include "php.h"
#include "zend_operators.h"
#include "datetime.h"
@@ -35,22 +33,21 @@
#include "php_parsedate.h"
-char *mon_full_names[] =
-{
+char *mon_full_names[] = {
"January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"
};
-char *mon_short_names[] =
-{
+
+char *mon_short_names[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
-char *day_full_names[] =
-{
+
+char *day_full_names[] = {
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
};
-char *day_short_names[] =
-{
+
+char *day_short_names[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
@@ -62,13 +59,12 @@ extern time_t timezone;
extern int daylight;
#endif
-static int phpday_tab[2][12] =
-{
+static int phpday_tab[2][12] = {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
-#define isleap(year) (((year%4) == 0 && (year%100)!=0) || (year%400)==0)
+#define isleap(year) (((year % 4) == 0 && (year % 100) != 0) || (year % 400)==0)
#define YEAR_BASE 1900
/* {{{ proto int time(void)
@@ -87,7 +83,8 @@ void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gm)
struct tm *ta, tmbuf;
time_t t, seconds;
int i, gmadjust, arg_count = ZEND_NUM_ARGS();
- int is_dst = -1, val, chgsecs = 0;
+ int is_dst = -1, chgsecs = 0;
+ long val;
if (arg_count > 7 || zend_get_parameters_array_ex(arg_count, arguments) == FAILURE) {
WRONG_PARAM_COUNT;
@@ -192,11 +189,11 @@ void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gm)
/* fall-through */
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;
@@ -218,16 +215,26 @@ 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);
t2 = *localtime(&seconds);
- if(t1.tm_isdst != t2.tm_isdst) {
+ if (t1.tm_isdst != t2.tm_isdst) {
seconds += (t1.tm_isdst == 1) ? 3600 : -3600;
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;
}
@@ -274,8 +281,7 @@ PHP_FUNCTION(gmmktime)
/* {{{ php_date
*/
-static void
-php_date(INTERNAL_FUNCTION_PARAMETERS, int gm)
+static void php_date(INTERNAL_FUNCTION_PARAMETERS, int gm)
{
pval **format, **timestamp;
time_t the_time;
@@ -398,7 +404,7 @@ php_date(INTERNAL_FUNCTION_PARAMETERS, int gm)
size += 2;
break;
case '\\':
- if(i < Z_STRLEN_PP(format)-1) {
+ if (i < Z_STRLEN_PP(format) - 1) {
i++;
}
size ++;
@@ -418,9 +424,9 @@ php_date(INTERNAL_FUNCTION_PARAMETERS, int gm)
for (i = 0; i < Z_STRLEN_PP(format); i++) {
switch (Z_STRVAL_PP(format)[i]) {
case '\\':
- if(i < Z_STRLEN_PP(format)-1) {
+ if (i < Z_STRLEN_PP(format) - 1) {
char ch[2];
- ch[0]=Z_STRVAL_PP(format)[i+1];
+ ch[0]=Z_STRVAL_PP(format)[i + 1];
ch[1]='\0';
strcat(Z_STRVAL_P(return_value), ch);
i++;
@@ -572,8 +578,8 @@ php_date(INTERNAL_FUNCTION_PARAMETERS, int gm)
strcat(Z_STRVAL_P(return_value), tmp_buff);
break;
case 'r':
-#if HAVE_TM_GMTOFF
- sprintf(tmp_buff, "%3s, %2d %3s %04d %02d:%02d:%02d %c%02d%02d",
+#if HAVE_TM_GMTOFF
+ sprintf(tmp_buff, "%3s, %2d %3s %04d %02d:%02d:%02d %c%02d%02d",
day_short_names[ta->tm_wday],
ta->tm_mday,
mon_short_names[ta->tm_mon],
@@ -586,7 +592,7 @@ php_date(INTERNAL_FUNCTION_PARAMETERS, int gm)
abs( (ta->tm_gmtoff % 3600) / 60 )
);
#else
- sprintf(tmp_buff, "%3s, %2d %3s %04d %02d:%02d:%02d %c%02d%02d",
+ sprintf(tmp_buff, "%3s, %2d %3s %04d %02d:%02d:%02d %c%02d%02d",
day_short_names[ta->tm_wday],
ta->tm_mday,
mon_short_names[ta->tm_mon],
@@ -602,7 +608,7 @@ php_date(INTERNAL_FUNCTION_PARAMETERS, int gm)
strcat(Z_STRVAL_P(return_value), tmp_buff);
break;
case 'W': /* ISO-8601 week number of year, weeks starting on Monday */
- wd = ta->tm_wday==0 ? 6 : ta->tm_wday-1;/* weekday */
+ wd = ta->tm_wday == 0 ? 6 : ta->tm_wday - 1; /* weekday */
yd = ta->tm_yday + 1; /* days since January 1st */
fd = (7 + wd - yd % 7+ 1) % 7; /* weekday (1st January) */
@@ -759,11 +765,10 @@ PHP_FUNCTION(getdate)
/* {{{ php_std_date
Return date string in standard format for http headers */
-char *php_std_date(time_t t)
+char *php_std_date(time_t t TSRMLS_DC)
{
struct tm *tm1, tmbuf;
char *str;
- TSRMLS_FETCH();
tm1 = php_gmtime_r(&t, &tmbuf);
str = emalloc(81);
@@ -772,18 +777,18 @@ char *php_std_date(time_t t)
day_short_names[tm1->tm_wday],
tm1->tm_mday,
mon_short_names[tm1->tm_mon],
- tm1->tm_year+1900,
+ tm1->tm_year + 1900,
tm1->tm_hour, tm1->tm_min, tm1->tm_sec);
} else {
snprintf(str, 80, "%s, %02d-%s-%02d %02d:%02d:%02d GMT",
day_short_names[tm1->tm_wday],
tm1->tm_mday,
mon_short_names[tm1->tm_mon],
- ((tm1->tm_year)%100),
+ ((tm1->tm_year) % 100),
tm1->tm_hour, tm1->tm_min, tm1->tm_sec);
}
- str[79]=0;
+ str[79] = 0;
return (str);
}
/* }}} */
@@ -854,11 +859,13 @@ void _php_strftime(INTERNAL_FUNCTION_PARAMETERS, int gm)
while ((real_len=strftime(buf, buf_len, format, ta))==buf_len || real_len==0) {
buf_len *= 2;
buf = (char *) erealloc(buf, buf_len);
- if(!--max_reallocs) break;
+ if (!--max_reallocs) {
+ break;
+ }
}
- if(real_len && real_len != buf_len) {
- buf = (char *) erealloc(buf, real_len+1);
+ if (real_len && real_len != buf_len) {
+ buf = (char *) erealloc(buf, real_len + 1);
RETURN_STRINGL(buf, real_len, 0);
}
efree(buf);
diff --git a/ext/standard/head.c b/ext/standard/head.c
index c993664269..cab62e6c69 100644
--- a/ext/standard/head.c
+++ b/ext/standard/head.c
@@ -98,14 +98,14 @@ PHPAPI int php_setcookie(char *name, int name_len, char *value, int value_len, t
* pick an expiry date 1 year and 1 second in the past
*/
t = time(NULL) - 31536001;
- dt = php_std_date(t);
+ dt = php_std_date(t TSRMLS_CC);
sprintf(cookie, "Set-Cookie: %s=deleted; expires=%s", name, dt);
efree(dt);
} else {
sprintf(cookie, "Set-Cookie: %s=%s", name, value ? encoded_value : "");
if (expires > 0) {
strcat(cookie, "; expires=");
- dt = php_std_date(expires);
+ dt = php_std_date(expires TSRMLS_CC);
strcat(cookie, dt);
efree(dt);
}
diff --git a/ext/standard/tests/time/bug27719.phpt b/ext/standard/tests/time/bug27719.phpt
index 991f9e8820..926fc582e2 100644
--- a/ext/standard/tests/time/bug27719.phpt
+++ b/ext/standard/tests/time/bug27719.phpt
@@ -2,13 +2,64 @@
Bug #27719: mktime returns incorrect timestamp for dst days
--FILE--
<?php
- putenv("TZ=EST");
-
- echo mktime(0, 0, 0, 4, 4, 2004, 0) . "\n";
- echo mktime(0, 0, 0, 4, 4, 2004, 1) . "\n";
- echo mktime(0, 0, 0, 4, 4, 2004, -1) . "\n";
+ putenv("TZ=EST"); // No DST
+ $a = mktime(0, 0, 0, 4, 4, 2004, 0);
+ $b = mktime(0, 0, 0, 4, 4, 2004, 1);
+ $c = mktime(0, 0, 0, 4, 4, 2004, -1);
+ echo "$a ".date("m/d/y h:i:s\n",$a);
+ echo "$b ".date("m/d/y h:i:s\n",$b);
+ echo "$c ".date("m/d/y h:i:s\n",$c);
+ echo "\n";
+ putenv("TZ=EST5DST"); // DST not in effect
+ $a = mktime(0, 0, 0, 2, 4, 2004, 0);
+ $b = mktime(0, 0, 0, 2, 4, 2004, 1);
+ $c = mktime(0, 0, 0, 2, 4, 2004, -1);
+ echo "$a ".date("m/d/y h:i:s\n",$a);
+ echo "$b ".date("m/d/y h:i:s\n",$b);
+ echo "$c ".date("m/d/y h:i:s\n",$c);
+ echo "\n";
+ putenv("TZ=EST5DST"); // Just before DST changeover
+ $a = mktime(0, 0, 0, 4, 4, 2004, 0);
+ $b = mktime(0, 0, 0, 4, 4, 2004, 1);
+ $c = mktime(0, 0, 0, 4, 4, 2004, -1);
+ echo "$a ".date("m/d/y h:i:s\n",$a);
+ echo "$b ".date("m/d/y h:i:s\n",$b);
+ echo "$c ".date("m/d/y h:i:s\n",$c);
+ echo "\n";
+ putenv("TZ=EST5DST"); // Just after DST changeover
+ $a = mktime(3, 0, 0, 4, 4, 2004, 0);
+ $b = mktime(3, 0, 0, 4, 4, 2004, 1);
+ $c = mktime(3, 0, 0, 4, 4, 2004, -1);
+ echo "$a ".date("m/d/y h:i:s\n",$a);
+ echo "$b ".date("m/d/y h:i:s\n",$b);
+ echo "$c ".date("m/d/y h:i:s\n",$c);
+ echo "\n";
+ putenv("TZ=EST5DST"); // DST in effect
+ $a = mktime(0, 0, 0, 6, 4, 2004, 0);
+ $b = mktime(0, 0, 0, 6, 4, 2004, 1);
+ $c = mktime(0, 0, 0, 6, 4, 2004, -1);
+ echo "$a ".date("m/d/y h:i:s\n",$a);
+ echo "$b ".date("m/d/y h:i:s\n",$b);
+ echo "$c ".date("m/d/y h:i:s\n",$c);
+ echo "\n";
?>
--EXPECT--
-1081054800
-1081051200
-1081054800
+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