summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerick Rethans <derick@php.net>2005-07-03 14:27:31 +0000
committerDerick Rethans <derick@php.net>2005-07-03 14:27:31 +0000
commited02f202f017d3c1ebddb202a0fc224cce1b9e78 (patch)
treee0e39df1eeb78ea8b3fa7604094e4c39b22f47bf
parentf4b5a5195210e6e3be439386f05f909248804ae7 (diff)
downloadphp-git-ed02f202f017d3c1ebddb202a0fc224cce1b9e78.tar.gz
- Fixed bug #30096 (gmmktime does not return the corrent time).
- Re-implemented mktime and gmmktime with new date time library. - Added testcase for bug #30096, updated test cases for E_STRICT warning of is_dst parameter usage for mktime/gmmktime.
-rw-r--r--NEWS1
-rw-r--r--ext/date/php_date.c101
-rw-r--r--ext/date/php_date.h5
-rw-r--r--ext/date/tests/bug30096.phpt48
-rw-r--r--ext/standard/basic_functions.c2
-rw-r--r--ext/standard/datetime.c204
-rw-r--r--ext/standard/datetime.h3
-rw-r--r--ext/standard/tests/time/003.phpt2
-rw-r--r--ext/standard/tests/time/bug27719.phpt2
-rw-r--r--ext/standard/tests/time/mktime.phpt2
10 files changed, 161 insertions, 209 deletions
diff --git a/NEWS b/NEWS
index 4946a4ce0c..a1837ffe5d 100644
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,7 @@ PHP NEWS
- Fixed bug #30828 (debug_backtrace() reports incorrect class in overridden
methods). (Dmitry)
- Fixed bug #30519 (Interface not existing says Class not found). (Dmitry)
+- Fixed bug #30096 (gmmktime does not return the corrent time). (Derick)
- Fixed bug #30052 (Crash on shutdown after odbc_pconnect()). (Edin)
- Fixed bug #28377 (debug_backtrace is intermittently passing args). (Dmitry)
- Fixed bug #27268 (Bad references accentuated by clone). (Dmitry)
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index 3aa89c6106..40af3f92d9 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -31,6 +31,8 @@
function_entry date_functions[] = {
PHP_FE(date, NULL)
PHP_FE(gmdate, NULL)
+ PHP_FE(mktime, NULL)
+ PHP_FE(gmmktime, NULL)
PHP_FE(strtotime, NULL)
PHP_FE(date_timezone_set, NULL)
PHP_FE(date_timezone_get, NULL)
@@ -400,6 +402,105 @@ PHP_FUNCTION(strtotime)
}
/* }}} */
+PHPAPI static void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gmt)
+{
+ long hou, min, sec, mon, day, yea, dst = -1;;
+ timelib_time *now;
+ timelib_tzinfo *tzi;
+ long ts, adjust_seconds = 0;
+ int error;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lllllll", &hou, &min, &sec, &mon, &day, &yea, &dst) == FAILURE) {
+ RETURN_FALSE;
+ }
+ /* Initialize structure with current time */
+ now = timelib_time_ctor();
+ if (gmt) {
+ timelib_unixtime2gmt(now, (timelib_sll) time(NULL));
+ } else {
+ tzi = get_timezone_info(TSRMLS_C);
+ timelib_unixtime2local(now, (timelib_sll) time(NULL), tzi);
+ }
+ /* Fill in the new data */
+ switch (ZEND_NUM_ARGS()) {
+ case 7:
+ /* break intentionally missing */
+ case 6:
+ now->y = yea;
+ /* break intentionally missing again */
+ case 5:
+ now->d = day;
+ /* break missing intentionally here too */
+ case 4:
+ now->m = mon;
+ /* and here */
+ case 3:
+ now->s = sec;
+ /* yup, this break isn't here on purpose too */
+ case 2:
+ now->i = min;
+ /* last intentionally missing break */
+ case 1:
+ now->h = hou;
+ break;
+ default:
+ php_error_docref(NULL TSRMLS_CC, E_STRICT, "You should be using the time() function instead.");
+ }
+ /* Update the timestamp */
+ if (gmt) {
+ timelib_update_ts(now, NULL);
+ } else {
+ timelib_update_ts(now, tzi);
+ }
+ /* Support for the deprecated is_dst parameter */
+ if (dst != -1) {
+ php_error_docref(NULL TSRMLS_CC, E_STRICT, "The is_dst parameter is deprecated.");
+ if (gmt) {
+ /* GMT never uses DST */
+ if (dst == 1) {
+ adjust_seconds = -3600;
+ }
+ } else {
+ /* Figure out is_dst for current TS */
+ timelib_time_offset *tmp_offset;
+ tmp_offset = timelib_get_time_zone_info(now->sse, tzi);
+ if (dst == 1 && tmp_offset->is_dst == 0) {
+ adjust_seconds = -3600;
+ }
+ if (dst == 0 && tmp_offset->is_dst == 1) {
+ adjust_seconds = +3600;
+ }
+ }
+ }
+ /* Clean up and return */
+ ts = timelib_date_to_int(now, &error);
+ ts += adjust_seconds;
+
+ timelib_time_dtor(now);
+
+ if (error) {
+ RETURN_FALSE;
+ } else {
+ RETURN_LONG(ts);
+ }
+}
+
+/* {{{ proto int mktime(int hour, int min, int sec, int mon, int day, int year)
+ Get UNIX timestamp for a date */
+PHP_FUNCTION(mktime)
+{
+ php_mktime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto int gmmktime(int hour, int min, int sec, int mon, int day, int year)
+ Get UNIX timestamp for a GMT date */
+PHP_FUNCTION(gmmktime)
+{
+ php_mktime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
PHP_FUNCTION(date_timezone_set)
{
char *zone;
diff --git a/ext/date/php_date.h b/ext/date/php_date.h
index 5b08a29024..470546f485 100644
--- a/ext/date/php_date.h
+++ b/ext/date/php_date.h
@@ -27,6 +27,10 @@ extern zend_module_entry date_module_entry;
PHP_FUNCTION(date);
PHP_FUNCTION(gmdate);
PHP_FUNCTION(strtotime);
+
+PHP_FUNCTION(mktime);
+PHP_FUNCTION(gmmktime);
+
PHP_FUNCTION(date_timezone_set);
PHP_FUNCTION(date_timezone_get);
@@ -49,5 +53,6 @@ ZEND_END_MODULE_GLOBALS(date)
/* Backwards compability wrapper */
signed long php_parse_date(char *string, signed long *now);
+PHPAPI static void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gmt);
#endif /* PHP_DATE_H */
diff --git a/ext/date/tests/bug30096.phpt b/ext/date/tests/bug30096.phpt
new file mode 100644
index 0000000000..fa4f716ee6
--- /dev/null
+++ b/ext/date/tests/bug30096.phpt
@@ -0,0 +1,48 @@
+--TEST--
+Bug #30096 (gmmktime does not return the corrent time)
+--INI--
+error_reporting=2047
+--FILE--
+<?php
+echo "no dst --> dst\n";
+$ts = -1;
+gm_date_check(01,00,00,03,27,2005);
+gm_date_check(02,00,00,03,27,2005);
+gm_date_check(03,00,00,03,27,2005);
+gm_date_check(04,00,00,03,27,2005);
+
+echo "\ndst --> no dst\n";
+$ts = -1;
+gm_date_check(01,00,00,10,30,2005);
+gm_date_check(02,00,00,10,30,2005);
+gm_date_check(03,00,00,10,30,2005);
+gm_date_check(04,00,00,10,30,2005);
+
+function gm_date_check($hour, $minute, $second, $month, $day, $year) {
+ global $ts, $tsold;
+
+ echo "gmmktime($hour,$minute,$second,$month,$day,$year): ";
+
+ $tsold = $ts;
+ $ts = gmmktime($hour, $minute, $second, $month, $day, $year);
+
+ echo $ts, " | gmdate('r', $ts):", gmdate('r', $ts);
+ if ($tsold > 0) {
+ echo " | Diff: " . ($ts - $tsold);
+ }
+ echo "\n";
+}
+
+?>
+--EXPECT--
+no dst --> dst
+gmmktime(1,0,0,3,27,2005): 1111885200 | gmdate('r', 1111885200):Sun, 27 Mar 2005 01:00:00 +0000
+gmmktime(2,0,0,3,27,2005): 1111888800 | gmdate('r', 1111888800):Sun, 27 Mar 2005 02:00:00 +0000 | Diff: 3600
+gmmktime(3,0,0,3,27,2005): 1111892400 | gmdate('r', 1111892400):Sun, 27 Mar 2005 03:00:00 +0000 | Diff: 3600
+gmmktime(4,0,0,3,27,2005): 1111896000 | gmdate('r', 1111896000):Sun, 27 Mar 2005 04:00:00 +0000 | Diff: 3600
+
+dst --> no dst
+gmmktime(1,0,0,10,30,2005): 1130634000 | gmdate('r', 1130634000):Sun, 30 Oct 2005 01:00:00 +0000
+gmmktime(2,0,0,10,30,2005): 1130637600 | gmdate('r', 1130637600):Sun, 30 Oct 2005 02:00:00 +0000 | Diff: 3600
+gmmktime(3,0,0,10,30,2005): 1130641200 | gmdate('r', 1130641200):Sun, 30 Oct 2005 03:00:00 +0000 | Diff: 3600
+gmmktime(4,0,0,10,30,2005): 1130644800 | gmdate('r', 1130644800):Sun, 30 Oct 2005 04:00:00 +0000 | Diff: 3600
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 856a06c62a..e86b726295 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -169,8 +169,6 @@ function_entry basic_functions[] = {
PHP_FE(time_sleep_until, NULL)
#endif
PHP_FE(time, NULL)
- PHP_FE(mktime, NULL)
- PHP_FE(gmmktime, NULL)
#if HAVE_STRPTIME
PHP_FE(strptime, NULL)
#endif
diff --git a/ext/standard/datetime.c b/ext/standard/datetime.c
index 9f1a9ce543..5e1933f5e9 100644
--- a/ext/standard/datetime.c
+++ b/ext/standard/datetime.c
@@ -77,210 +77,6 @@ PHP_FUNCTION(time)
}
/* }}} */
-/* {{{ php_mktime
- */
-PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gm)
-{
- pval **arguments[7];
- struct tm *ta, tmbuf;
- time_t t, seconds;
- int i, gmadjust, arg_count = ZEND_NUM_ARGS();
- int is_dst = -1, chgsecs = 0;
- long val;
-
- if (arg_count > 7 || zend_get_parameters_array_ex(arg_count, arguments) == FAILURE) {
- WRONG_PARAM_COUNT;
- }
- /* convert supplied arguments to longs */
- for (i = 0; i < arg_count; i++) {
- convert_to_long_ex(arguments[i]);
- }
- t = time(NULL);
-#ifdef HAVE_TZSET
- tzset();
-#endif
- /*
- ** Set default time parameters with local time values,
- ** EVEN when some GMT time parameters are specified!
- ** This may give strange result, with PHP gmmktime(0, 0, 0),
- ** which is assumed to return GMT midnight time
- ** for today (in localtime), so that the result time may be
- ** AFTER or BEFORE the current time.
- ** May be we should initialize tn using gmtime(), so that
- ** default parameters for PHP gmmktime would be the current
- ** GMT time values...
- */
- ta = php_localtime_r(&t, &tmbuf);
-
- /* Let DST be unknown. mktime() should compute the right value
- ** and behave correctly. Unless the user overrides this.
- */
- ta->tm_isdst = -1;
-
- /*
- ** Now change date values with supplied parameters.
- */
- switch(arg_count) {
- case 7: /* daylight saving time flag */
-#ifdef PHP_WIN32
- if (daylight > 0) {
- ta->tm_isdst = is_dst = Z_LVAL_PP(arguments[6]);
- } else {
- ta->tm_isdst = is_dst = 0;
- }
-#else
- ta->tm_isdst = is_dst = Z_LVAL_PP(arguments[6]);
-#endif
- /* fall-through */
- case 6: /* year */
- /* special case:
- a zero in year, month and day is considered illegal
- as it would be interpreted as 30.11.1999 otherwise
- */
- if ( ( Z_LVAL_PP(arguments[5])==0)
- &&(Z_LVAL_PP(arguments[4])==0)
- &&(Z_LVAL_PP(arguments[3])==0)
- ) {
- RETURN_LONG(-1);
- }
-
- /*
- ** Accept parameter in range 0..1000 interpreted as 1900..2900
- ** (if 100 is given, it means year 2000)
- ** or in range 1001..9999 interpreted as is (this will store
- ** negative tm_year for years in range 1001..1899)
- ** This function is then Y2K ready, and accepts a wide range of
- ** dates including the whole gregorian calendar.
- ** But it cannot represent ancestral dates prior to year 1001.
- ** Additionally, input parameters of 0..70 are mapped to 100..170
- */
- if (Z_LVAL_PP(arguments[5]) < 70)
- ta->tm_year = Z_LVAL_PP(arguments[5]) + 100;
- else
- ta->tm_year = Z_LVAL_PP(arguments[5])
- - ((Z_LVAL_PP(arguments[5]) > 1000) ? 1900 : 0);
- /* fall-through */
- case 5: /* day in month (1-based) */
- val = (*arguments[4])->value.lval;
- if (val < 1) {
- chgsecs += (1-val) * 60*60*24;
- val = 1;
- }
- ta->tm_mday = val;
- /* fall-through */
- case 4: /* month (zero-based) */
- val = (*arguments[3])->value.lval - 1;
- while (val < 0) {
- val += 12; ta->tm_year--;
- }
- ta->tm_mon = val;
- /* fall-through */
- case 3: /* second */
- val = (*arguments[2])->value.lval;
- if (val < 1) {
- chgsecs += (1-val); val = 1;
- }
- ta->tm_sec = val;
- /* fall-through */
- case 2: /* minute */
- val = (*arguments[1])->value.lval;
- if (val < 1) {
- chgsecs += (1-val) * 60; val = 1;
- }
- ta->tm_min = val;
- /* fall-through */
- case 1: /* hour */
- val = (*arguments[0])->value.lval;
- /*
- 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;
- }
- ta->tm_hour = val;
- /* fall-through */
- case 0:
- break;
- }
-
- t = mktime(ta);
-
-#ifdef PHP_WIN32
- if (t - chgsecs < 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Windows does not support negative values for this function");
- RETURN_LONG(-1);
- }
-#endif
-
- 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) {
- 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;
- }
-
- if (gm) {
-#if HAVE_TM_GMTOFF
- /*
- ** mktime(ta) very nicely just filled ta->tm_gmtoff with
- ** the exactly right value for adjustment if we want GMT.
- */
- gmadjust = ta->tm_gmtoff;
-#else
- /*
- ** If correcting for daylight savings time, we set the adjustment to
- ** the value of timezone - 3600 seconds.
- */
-#ifdef __CYGWIN__
- gmadjust = -(is_dst ? _timezone - 3600 : _timezone);
-#else
- gmadjust = -(is_dst ? timezone - 3600 : timezone);
-#endif
-#endif
- seconds += gmadjust;
- }
-
- RETURN_LONG(seconds);
-}
-/* }}} */
-
-/* {{{ proto int mktime(int hour, int min, int sec, int mon, int day, int year)
- Get UNIX timestamp for a date */
-PHP_FUNCTION(mktime)
-{
- php_mktime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
-}
-/* }}} */
-
-/* {{{ proto int gmmktime(int hour, int min, int sec, int mon, int day, int year)
- Get UNIX timestamp for a GMT date */
-PHP_FUNCTION(gmmktime)
-{
- php_mktime(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
-}
-/* }}} */
-
/* {{{ php_idate
*/
PHPAPI int php_idate(char format, int timestamp, int gm)
diff --git a/ext/standard/datetime.h b/ext/standard/datetime.h
index d1d3c04fac..4c1e39fb50 100644
--- a/ext/standard/datetime.h
+++ b/ext/standard/datetime.h
@@ -23,8 +23,6 @@
#define DATETIME_H
PHP_FUNCTION(time);
-PHP_FUNCTION(mktime);
-PHP_FUNCTION(gmmktime);
PHP_FUNCTION(idate);
PHP_FUNCTION(localtime);
PHP_FUNCTION(getdate);
@@ -39,7 +37,6 @@ PHP_FUNCTION(gmstrftime);
PHPAPI int php_idate(char format, int timestamp, int gm);
PHPAPI char *php_std_date(time_t t TSRMLS_DC);
-PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gm);
#if HAVE_STRFTIME
PHPAPI void _php_strftime(INTERNAL_FUNCTION_PARAMETERS, int gm);
#endif
diff --git a/ext/standard/tests/time/003.phpt b/ext/standard/tests/time/003.phpt
index 0bf1c84e35..6b44e4d067 100644
--- a/ext/standard/tests/time/003.phpt
+++ b/ext/standard/tests/time/003.phpt
@@ -1,5 +1,7 @@
--TEST--
Check for mktime with out-of-range parameters
+--INI--
+error_reporting=2047
--FILE--
<?php
# MacOS/X libc implementation doesn't treat out-of-range values
diff --git a/ext/standard/tests/time/bug27719.phpt b/ext/standard/tests/time/bug27719.phpt
index c8a51bea1e..cff6fdd2fe 100644
--- a/ext/standard/tests/time/bug27719.phpt
+++ b/ext/standard/tests/time/bug27719.phpt
@@ -1,5 +1,7 @@
--TEST--
Bug #27719: mktime returns incorrect timestamp for dst days
+--INI--
+error_reporting=2047
--FILE--
<?php /* $Id$ */
putenv("TZ=EST"); // No DST
diff --git a/ext/standard/tests/time/mktime.phpt b/ext/standard/tests/time/mktime.phpt
index 8914ea0787..304d9bad3a 100644
--- a/ext/standard/tests/time/mktime.phpt
+++ b/ext/standard/tests/time/mktime.phpt
@@ -1,5 +1,7 @@
--TEST--
mktime()
+--INI--
+error_reporting=2047
--FILE--
<?php /* $Id$ */
$timezones = array(