- 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)
}
/* }}} */
+/* {{{ 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)
}
/* }}} */
+/* {{{ 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)
{
/* 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);
--- /dev/null
+--TEST--
+Bug #35425 (idate() function ignores timezone settings)
+--FILE--
+<?php
+putenv('TZ=America/Montreal');
+
+$time = mktime(1,1,1,1,1,2005);
+foreach (array('B','d','h','H','i','I','L','m','s','t','U','w','W','y','Y','z','Z') as $v) {
+ var_dump(idate($v, $time));
+}
+
+?>
+--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)
PHP_FE(strptime, NULL)
#endif
- PHP_FE(idate, NULL)
-
PHP_FE(flush, NULL)
PHP_FE(wordwrap, NULL)
PHP_FE(htmlspecialchars, NULL)
"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)
#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 */