derick Sun Jul 3 10:27:32 2005 EDT Added files: /php-src/ext/date/tests bug30096.phpt
Modified files: /php-src NEWS /php-src/ext/standard basic_functions.c datetime.c datetime.h /php-src/ext/standard/tests/time 003.phpt bug27719.phpt mktime.phpt /php-src/ext/date php_date.c php_date.h Log: - 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.
http://cvs.php.net/diff.php/php-src/NEWS?r1=1.1972&r2=1.1973&ty=u Index: php-src/NEWS diff -u php-src/NEWS:1.1972 php-src/NEWS:1.1973 --- php-src/NEWS:1.1972 Sat Jul 2 19:04:34 2005 +++ php-src/NEWS Sun Jul 3 10:27:31 2005 @@ -19,6 +19,7 @@ - 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) http://cvs.php.net/diff.php/php-src/ext/standard/basic_functions.c?r1=1.721&r2=1.722&ty=u Index: php-src/ext/standard/basic_functions.c diff -u php-src/ext/standard/basic_functions.c:1.721 php-src/ext/standard/basic_functions.c:1.722 --- php-src/ext/standard/basic_functions.c:1.721 Thu Jun 30 17:38:06 2005 +++ php-src/ext/standard/basic_functions.c Sun Jul 3 10:27:31 2005 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: basic_functions.c,v 1.721 2005/06/30 21:38:06 derick Exp $ */ +/* $Id: basic_functions.c,v 1.722 2005/07/03 14:27:31 derick Exp $ */ #include "php.h" #include "php_streams.h" @@ -169,8 +169,6 @@ 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 http://cvs.php.net/diff.php/php-src/ext/standard/datetime.c?r1=1.130&r2=1.131&ty=u Index: php-src/ext/standard/datetime.c diff -u php-src/ext/standard/datetime.c:1.130 php-src/ext/standard/datetime.c:1.131 --- php-src/ext/standard/datetime.c:1.130 Thu Jun 30 17:38:06 2005 +++ php-src/ext/standard/datetime.c Sun Jul 3 10:27:31 2005 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: datetime.c,v 1.130 2005/06/30 21:38:06 derick Exp $ */ +/* $Id: datetime.c,v 1.131 2005/07/03 14:27:31 derick Exp $ */ #if HAVE_STRPTIME #define _XOPEN_SOURCE @@ -77,210 +77,6 @@ } /* }}} */ -/* {{{ 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) http://cvs.php.net/diff.php/php-src/ext/standard/datetime.h?r1=1.20&r2=1.21&ty=u Index: php-src/ext/standard/datetime.h diff -u php-src/ext/standard/datetime.h:1.20 php-src/ext/standard/datetime.h:1.21 --- php-src/ext/standard/datetime.h:1.20 Thu Jun 30 17:38:06 2005 +++ php-src/ext/standard/datetime.h Sun Jul 3 10:27:31 2005 @@ -17,14 +17,12 @@ +----------------------------------------------------------------------+ */ -/* $Id: datetime.h,v 1.20 2005/06/30 21:38:06 derick Exp $ */ +/* $Id: datetime.h,v 1.21 2005/07/03 14:27:31 derick Exp $ */ #ifndef DATETIME_H #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 @@ 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 http://cvs.php.net/diff.php/php-src/ext/standard/tests/time/003.phpt?r1=1.4&r2=1.5&ty=u Index: php-src/ext/standard/tests/time/003.phpt diff -u php-src/ext/standard/tests/time/003.phpt:1.4 php-src/ext/standard/tests/time/003.phpt:1.5 --- php-src/ext/standard/tests/time/003.phpt:1.4 Wed May 19 04:45:23 2004 +++ php-src/ext/standard/tests/time/003.phpt Sun Jul 3 10:27:31 2005 @@ -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 http://cvs.php.net/diff.php/php-src/ext/standard/tests/time/bug27719.phpt?r1=1.5&r2=1.6&ty=u Index: php-src/ext/standard/tests/time/bug27719.phpt diff -u php-src/ext/standard/tests/time/bug27719.phpt:1.5 php-src/ext/standard/tests/time/bug27719.phpt:1.6 --- php-src/ext/standard/tests/time/bug27719.phpt:1.5 Thu Jun 30 17:38:06 2005 +++ php-src/ext/standard/tests/time/bug27719.phpt Sun Jul 3 10:27:31 2005 @@ -1,7 +1,9 @@ --TEST-- Bug #27719: mktime returns incorrect timestamp for dst days +--INI-- +error_reporting=2047 --FILE-- -<?php /* $Id: bug27719.phpt,v 1.5 2005/06/30 21:38:06 derick Exp $ */ +<?php /* $Id: bug27719.phpt,v 1.6 2005/07/03 14:27:31 derick Exp $ */ putenv("TZ=EST"); // No DST $a = mktime(0, 0, 0, 4, 4, 2004, 0); $b = mktime(0, 0, 0, 4, 4, 2004, 1); http://cvs.php.net/diff.php/php-src/ext/standard/tests/time/mktime.phpt?r1=1.5&r2=1.6&ty=u Index: php-src/ext/standard/tests/time/mktime.phpt diff -u php-src/ext/standard/tests/time/mktime.phpt:1.5 php-src/ext/standard/tests/time/mktime.phpt:1.6 --- php-src/ext/standard/tests/time/mktime.phpt:1.5 Tue Mar 30 20:00:55 2004 +++ php-src/ext/standard/tests/time/mktime.phpt Sun Jul 3 10:27:31 2005 @@ -1,7 +1,9 @@ --TEST-- mktime() +--INI-- +error_reporting=2047 --FILE-- -<?php /* $Id: mktime.phpt,v 1.5 2004/03/31 01:00:55 abies Exp $ */ +<?php /* $Id: mktime.phpt,v 1.6 2005/07/03 14:27:31 derick Exp $ */ $timezones = array( 'GMT0', 'Europe/London' http://cvs.php.net/diff.php/php-src/ext/date/php_date.c?r1=1.20&r2=1.21&ty=u Index: php-src/ext/date/php_date.c diff -u php-src/ext/date/php_date.c:1.20 php-src/ext/date/php_date.c:1.21 --- php-src/ext/date/php_date.c:1.20 Sat Jul 2 17:19:25 2005 +++ php-src/ext/date/php_date.c Sun Jul 3 10:27:31 2005 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_date.c,v 1.20 2005/07/02 21:19:25 derick Exp $ */ +/* $Id: php_date.c,v 1.21 2005/07/03 14:27:31 derick Exp $ */ #include "php.h" #include "php_streams.h" @@ -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 @@ } /* }}} */ +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; http://cvs.php.net/diff.php/php-src/ext/date/php_date.h?r1=1.7&r2=1.8&ty=u Index: php-src/ext/date/php_date.h diff -u php-src/ext/date/php_date.h:1.7 php-src/ext/date/php_date.h:1.8 --- php-src/ext/date/php_date.h:1.7 Sat Jul 2 17:19:25 2005 +++ php-src/ext/date/php_date.h Sun Jul 3 10:27:31 2005 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_date.h,v 1.7 2005/07/02 21:19:25 derick Exp $ */ +/* $Id: php_date.h,v 1.8 2005/07/03 14:27:31 derick Exp $ */ #ifndef PHP_DATE_H #define PHP_DATE_H @@ -27,6 +27,10 @@ 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 @@ /* 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 */ http://cvs.php.net/co.php/php-src/ext/date/tests/bug30096.phpt?r=1.1&p=1 Index: php-src/ext/date/tests/bug30096.phpt +++ php-src/ext/date/tests/bug30096.phpt --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
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php