From: Ilia Alshanetsky Date: Tue, 29 Nov 2005 20:19:56 +0000 (+0000) Subject: Fixed bug #35425 (idate() function ignores timezone settings). X-Git-Tag: php-5.1.2RC1~311 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=820b5aa9e4a068bdcd3f2024d79979a1e86c2af0;p=php Fixed bug #35425 (idate() function ignores timezone settings). --- diff --git a/NEWS b/NEWS index d4c204a001..d4b03e831e 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ PHP NEWS - Fixed bug #35431 (PDO crashes when using LAZY fetch with fetchAll). (Wez) - Fixed bug #35430 (PDO crashes on incorrect FETCH_FUNC use). (Tony) - Fixed bug #35427 (str_word_count() handles '-' incorrectly). (Ilia) +- Fixed bug #35425 (idate() function ignores timezone settings). (Ilia) - Fixed bug #35422 (strtotime() does not parse times with UTC as timezone). (Ilia) - Fixed bug #35414 (strtotime() no longer works with ordinal suffix). (Ilia) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 149f44ca30..6eae37b0ab 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -594,6 +594,104 @@ PHPAPI char *php_format_date(char *format, int format_len, time_t ts, int localt } /* }}} */ +/* {{{ php_idate + */ +PHPAPI int php_idate(char format, time_t ts, int localtime) +{ + timelib_time *t; + timelib_tzinfo *tzi; + int retval = -1; + timelib_time_offset *offset; + timelib_sll isoweek, isoyear; + + t = timelib_time_ctor(); + + if (!localtime) { + TSRMLS_FETCH(); + tzi = get_timezone_info(TSRMLS_C); + timelib_unixtime2local(t, ts, tzi); + } else { + tzi = NULL; + timelib_unixtime2gmt(t, ts); + } + + if (!localtime) { + if (t->zone_type == TIMELIB_ZONETYPE_ABBR) { + offset = timelib_time_offset_ctor(); + offset->offset = (t->z - (t->dst * 60)) * -60; + offset->leap_secs = 0; + offset->is_dst = t->dst; + offset->abbr = strdup(t->tz_abbr); + } else if (t->zone_type == TIMELIB_ZONETYPE_OFFSET) { + offset = timelib_time_offset_ctor(); + offset->offset = (t->z - (t->dst * 60)) * -60; + offset->leap_secs = 0; + offset->is_dst = t->dst; + offset->abbr = malloc(9); /* GMT±xxxx\0 */ + snprintf(offset->abbr, 9, "GMT%c%02d%02d", + !localtime ? ((offset->offset < 0) ? '-' : '+') : '+', + !localtime ? abs(offset->offset / 3600) : 0, + !localtime ? abs((offset->offset % 3600) / 60) : 0 ); + } else { + offset = timelib_get_time_zone_info(t->sse, t->tz_info); + } + } + + timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); + + switch (format) { + /* day */ + case 'd': case 'j': retval = (int) t->d; break; + + case 'w': retval = (int) timelib_day_of_week(t->y, t->m, t->d); break; + case 'z': retval = (int) timelib_day_of_year(t->y, t->m, t->d); break; + + /* week */ + case 'W': retval = (int) isoweek; break; /* iso weeknr */ + + /* month */ + case 'm': case 'n': retval = (int) t->m; break; + case 't': retval = (int) timelib_days_in_month(t->y, t->m); break; + + /* year */ + case 'L': retval = (int) timelib_is_leap((int) t->y); break; + case 'y': retval = (int) (t->y % 100); break; + case 'Y': retval = (int) t->y; break; + + /* Swatch Beat a.k.a. Internet Time */ + case 'B': + retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864); + while (retval < 0) { + retval += 1000; + } + retval = retval % 1000; + break; + + /* time */ + case 'g': case 'h': retval = (int) ((t->h % 12) ? (int) t->h % 12 : 12); break; + case 'H': case 'G': retval = (int) t->h; break; + case 'i': retval = (int) t->i; break; + case 's': retval = (int) t->s; break; + + /* timezone */ + case 'I': retval = (int) (!localtime ? offset->is_dst : 0); break; + case 'Z': retval = (int) (!localtime ? offset->offset : 0); break; + + case 'U': retval = (int) t->sse; break; + default: + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unrecognized date format token."); + break; + } + + if (!localtime) { + timelib_time_offset_dtor(offset); + } + timelib_time_dtor(t); + + return retval; +} +/* }}} */ + /* {{{ proto string date(string format [, long timestamp]) Format a local date/time */ PHP_FUNCTION(date) @@ -610,6 +708,31 @@ PHP_FUNCTION(gmdate) } /* }}} */ +/* {{{ proto int idate(string format [, int timestamp]) + Format a local time/date as integer */ +PHP_FUNCTION(idate) +{ + char *format; + int format_len; + time_t ts; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &format, &format_len, &ts) == FAILURE) { + RETURN_FALSE; + } + + if (format_len != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "idate format is one char"); + RETURN_FALSE; + } + + if (ZEND_NUM_ARGS() == 1) { + ts = time(NULL); + } + + RETURN_LONG(php_idate(format[0], ts, 0)); +} +/* }}} */ + /* {{{ php_date_set_tzdb - NOT THREADSAFE */ PHPAPI void php_date_set_tzdb(timelib_tzdb *tzdb) { diff --git a/ext/date/php_date.h b/ext/date/php_date.h index 08a03931d4..4fb8d4c9dc 100644 --- a/ext/date/php_date.h +++ b/ext/date/php_date.h @@ -91,6 +91,7 @@ ZEND_END_MODULE_GLOBALS(date) /* Backwards compability wrapper */ signed long php_parse_date(char *string, signed long *now); PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gmt); +PHPAPI int php_idate(char format, time_t ts, int localtime); #if HAVE_STRFTIME #define _php_strftime php_strftime PHPAPI void php_strftime(INTERNAL_FUNCTION_PARAMETERS, int gm); diff --git a/ext/date/tests/bug35425.phpt b/ext/date/tests/bug35425.phpt new file mode 100644 index 0000000000..4259b49a1c --- /dev/null +++ b/ext/date/tests/bug35425.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #35425 (idate() function ignores timezone settings) +--FILE-- + +--EXPECT-- +int(292) +int(1) +int(1) +int(1) +int(1) +int(0) +int(0) +int(1) +int(1) +int(31) +int(1104559261) +int(6) +int(53) +int(5) +int(2005) +int(0) +int(-18000) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index df5933f1a5..a4e1ced714 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -177,8 +177,6 @@ function_entry basic_functions[] = { PHP_FE(strptime, NULL) #endif - PHP_FE(idate, NULL) - PHP_FE(flush, NULL) PHP_FE(wordwrap, NULL) PHP_FE(htmlspecialchars, NULL) diff --git a/ext/standard/datetime.c b/ext/standard/datetime.c index 8f4c541099..77139133fc 100644 --- a/ext/standard/datetime.c +++ b/ext/standard/datetime.c @@ -53,163 +53,6 @@ char *day_short_names[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; -#if !defined(HAVE_TM_ZONE) && !defined(_TIMEZONE) && !defined(HAVE_DECLARED_TIMEZONE) -#ifdef NETWARE -#define timezone _timezone /* timezone is called '_timezone' in new version of LibC */ -#endif -extern time_t timezone; -extern int daylight; -#endif - -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 YEAR_BASE 1900 - -/* {{{ php_idate - */ -PHPAPI int php_idate(char format, int timestamp, int gm) -{ - time_t the_time; - struct tm *ta, tmbuf; - int h, beat, fd, wd, yd, wk; -#if !HAVE_TM_GMTOFF - long tzone; - char *tname[2]= {"GMT Standard Time", "BST"}; -#endif - - the_time = timestamp; - - if (gm) { - ta = php_gmtime_r(&the_time, &tmbuf); -#if !HAVE_TM_GMTOFF - tzone = 0; -#endif - } else { - ta = php_localtime_r(&the_time, &tmbuf); -#if !HAVE_TM_GMTOFF -#ifdef __CYGWIN__ - tzone = _timezone; -#else - tzone = timezone; -#endif - tname[0] = tzname[0]; -#endif - } - - switch (format) { - case 'U': /* seconds since the epoch */ - return (long)the_time; - case 'Y': /* year, numeric, 4 digits */ - return ta->tm_year + YEAR_BASE; - case 'z': /* day (of the year) */ - return ta->tm_yday; - case 'y': /* year, numeric, 2 digits */ - return (ta->tm_year) % 100; - case 'm': /* month, numeric */ - case 'n': - return ta->tm_mon + 1; - case 'd': /* day of the month, numeric */ - case 'j': - return ta->tm_mday; - case 'H': /* hour, numeric, 24 hour format */ - case 'G': - return ta->tm_hour; - case 'h': /* hour, numeric, 12 hour format */ - case 'g': - h = ta->tm_hour % 12; - if (h == 0) { - h = 12; - } - return h; - case 'i': /* minutes, numeric */ - return ta->tm_min; - case 's': /* seconds, numeric */ - return ta->tm_sec; - case 't': /* days in current month */ - return phpday_tab[isleap((ta->tm_year + YEAR_BASE))][ta->tm_mon]; - case 'w': /* day of the week, numeric EXTENSION */ - return ta->tm_wday; - case 'Z': /* timezone offset in seconds */ -#if HAVE_TM_GMTOFF - return ta->tm_gmtoff; -#else - return ta->tm_isdst ? -(tzone - 3600) : -tzone; -#endif - case 'L': /* boolean for leapyear */ - return isleap(ta->tm_year + YEAR_BASE) ? 1 : 0; - case 'B': /* Swatch Beat a.k.a. Internet Time */ - beat = (((((long)the_time) - (((long)the_time) - ((((long)the_time) % 86400) + 3600))) * 10) / 864); - while (beat < 0) { - beat += 1000; - } - beat = beat % 1000; - return beat; - case 'I': - return ta->tm_isdst; - case 'W': /* ISO-8601 week number of year, weeks starting on Monday */ - 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) */ - if ((yd <= 7 - fd) && fd > 3) { /* week is a last year week (52 or 53) */ - wk = (fd == 4 || (fd == 5 && isleap((ta->tm_year + YEAR_BASE - 1)))) ? 53 : 52; - } - /* week is a next year week (1) */ - else if (isleap((ta->tm_year + YEAR_BASE)) + 365 - yd < 3 - wd) { - wk = 1; - } - /* normal week */ - else { - wk = (yd + 6 - wd + fd) / 7 - (fd > 3); - } - return wk; - break; - default: - return 0; - } -} -/* }}} */ - -/* {{{ proto int idate(string format [, int timestamp]) - Format a local time/date as integer */ -PHP_FUNCTION(idate) -{ - zval **format, **timestamp; - int t, ret; - - switch (ZEND_NUM_ARGS()) { - case 1: - if (zend_get_parameters_ex(1, &format) == FAILURE) { - WRONG_PARAM_COUNT; - } - t = time(NULL); - break; - case 2: - if (zend_get_parameters_ex(2, &format, ×tamp) == FAILURE) { - WRONG_PARAM_COUNT; - } - convert_to_long_ex(timestamp); - t = Z_LVAL_PP(timestamp); - break; - default: - WRONG_PARAM_COUNT; - } - - convert_to_string_ex(format); - - if (Z_STRLEN_PP(format) != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "idate format is one char"); - RETURN_FALSE; - } - - ret = php_idate(Z_STRVAL_PP(format)[0], t, 0); - RETURN_LONG(ret); -} -/* }}} */ - /* {{{ php_std_date Return date string in standard format for http headers */ PHPAPI char *php_std_date(time_t t TSRMLS_DC) diff --git a/ext/standard/datetime.h b/ext/standard/datetime.h index 5c125ccfb8..70a29a9173 100644 --- a/ext/standard/datetime.h +++ b/ext/standard/datetime.h @@ -22,16 +22,10 @@ #ifndef DATETIME_H #define DATETIME_H -PHP_FUNCTION(time); -PHP_FUNCTION(idate); -PHP_FUNCTION(localtime); -PHP_FUNCTION(getdate); -PHP_FUNCTION(checkdate); #if HAVE_STRPTIME PHP_FUNCTION(strptime); #endif -PHPAPI int php_idate(char format, int timestamp, int gm); PHPAPI char *php_std_date(time_t t TSRMLS_DC); #endif /* DATETIME_H */