derick Thu Jan 17 18:49:55 2008 UTC Added files: (Branch: PHP_5_3) /php-src/ext/date/tests bug40743.phpt bug42910.phpt bug43527.phpt
Modified files: /php-src NEWS /php-src/ext/date php_date.c /php-src/ext/date/lib parse_date.c Log: - MFH: Added support for abbreviation and offset based timezone specifiers for DateTime::getOffset() and DateTime::getName(). - MFH: Fixed bug #43527 (DateTime created from a timestamp reports environment timezone). - MFH: Fixed bug #42190 (Constructing DateTime with TimeZone Indicator invalidates DateTimeZone).
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.72&r2=1.2027.2.547.2.965.2.73&diff_format=u Index: php-src/NEWS diff -u php-src/NEWS:1.2027.2.547.2.965.2.72 php-src/NEWS:1.2027.2.547.2.965.2.73 --- php-src/NEWS:1.2027.2.547.2.965.2.72 Wed Jan 16 14:21:07 2008 +++ php-src/NEWS Thu Jan 17 18:49:31 2008 @@ -11,6 +11,8 @@ - strtotime() / new DateTime - date_create_from_format() / DateTime::createFromFormat() - date_parse_from_format() + * support for abbreviation and offset based timezone specifiers for + DateTime::getOffset() and DateTime::getName(). - Added ability to use Traversable objects instead of plain arrays in ext/soap. (Joshua Reese, Dmitry) @@ -75,6 +77,8 @@ - Fixed possible crash in ext/soap because of uninitialized value. (Zdash Urf) +- Fixed bug #43527 (DateTime created from a timestamp reports environment + timezone). (Derick) - Fixed bug #43143 (Warning about empty IV with MCRYPT_MODE_ECB). (Derick) - Fixed bug #43136 (possible crash on script execution timeout. The EG(function_state_ptr) is completely removed, @@ -94,6 +98,8 @@ - Fixed bug #42548 (mysqli PROCEDURE calls can't return result sets). (hartmut) - Fixed bug #42509 (gmp leaks memory when gmp_init() not used). (Stas) - Fixed bug #42284 (duplicate of #39700). (Lars W) +- Fixed bug #42190 (Constructing DateTime with TimeZone Indicator invalidates + DateTimeZone). (Derick) - Fixed bug #42069 (parse_ini_file() allows using some non-alpha numeric characters). (Jani) - Fixed bug #41522 (PDO firebird driver returns null if it fails to connect). http://cvs.php.net/viewvc.cgi/php-src/ext/date/php_date.c?r1=1.43.2.45.2.51.2.8&r2=1.43.2.45.2.51.2.9&diff_format=u Index: php-src/ext/date/php_date.c diff -u php-src/ext/date/php_date.c:1.43.2.45.2.51.2.8 php-src/ext/date/php_date.c:1.43.2.45.2.51.2.9 --- php-src/ext/date/php_date.c:1.43.2.45.2.51.2.8 Sun Jan 13 18:42:19 2008 +++ php-src/ext/date/php_date.c Thu Jan 17 18:49:31 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_date.c,v 1.43.2.45.2.51.2.8 2008/01/13 18:42:19 derick Exp $ */ +/* $Id: php_date.c,v 1.43.2.45.2.51.2.9 2008/01/17 18:49:31 derick Exp $ */ #include "php.h" #include "php_streams.h" @@ -273,7 +273,17 @@ struct _php_timezone_obj { zend_object std; - timelib_tzinfo *tz; + int type; + union { + timelib_tzinfo *tz; // TIMELIB_ZONETYPE_ID; + timelib_sll utc_offset; // TIMELIB_ZONETYPE_OFFSET + struct // TIMELIB_ZONETYPE_ABBR + { + timelib_sll utc_offset; + char *abbr; + int dst; + } z; + } tzi; }; #define DATE_SET_CONTEXT \ @@ -820,7 +830,26 @@ ); break; case 'T': length = slprintf(buffer, 32, "%s", localtime ? offset->abbr : "GMT"); break; - case 'e': length = slprintf(buffer, 32, "%s", localtime ? t->tz_info->name : "UTC"); break; + case 'e': if (!localtime) { + length = slprintf(buffer, 32, "%s", "UTC"); + } else { + switch (t->zone_type) { + case TIMELIB_ZONETYPE_ID: + length = slprintf(buffer, 32, "%s", t->tz_info->name); + break; + case TIMELIB_ZONETYPE_ABBR: + length = slprintf(buffer, 32, "%s", offset->abbr); + break; + case TIMELIB_ZONETYPE_OFFSET: + length = slprintf(buffer, 32, "%c%02d:%02d", + ((offset->offset < 0) ? '-' : '+'), + abs(offset->offset / 3600), + abs((offset->offset % 3600) / 60) + ); + break; + } + } + break; case 'Z': length = slprintf(buffer, 32, "%d", localtime ? offset->offset : 0); break; /* full date/time */ @@ -1098,7 +1127,7 @@ now = timelib_time_ctor(); initial_ts = emalloc(25); - snprintf(initial_ts, 24, "@%ld", preset_ts); + snprintf(initial_ts, 24, "@%ld UTC", preset_ts); t = timelib_strtotime(initial_ts, strlen(initial_ts), NULL, DATE_TIMEZONEDB); /* we ignore the error here, as this should never fail */ timelib_update_ts(t, tzi); now->tz_info = tzi; @@ -1602,7 +1631,20 @@ zend_object_value new_ov = date_object_new_timezone_ex(old_obj->std.ce, &new_obj TSRMLS_CC); zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); - new_obj->tz = old_obj->tz; + new_obj->type = old_obj->type; + switch (new_obj->type) { + case TIMELIB_ZONETYPE_ID: + new_obj->tzi.tz = old_obj->tzi.tz; + break; + case TIMELIB_ZONETYPE_OFFSET: + new_obj->tzi.utc_offset = old_obj->tzi.utc_offset; + break; + case TIMELIB_ZONETYPE_ABBR: + new_obj->tzi.z.utc_offset = old_obj->tzi.z.utc_offset; + new_obj->tzi.z.dst = old_obj->tzi.z.dst; + new_obj->tzi.z.abbr = old_obj->tzi.z.abbr; + break; + } return new_ov; } @@ -1626,6 +1668,9 @@ { php_timezone_obj *intern = (php_timezone_obj *)object; + if (intern->type == TIMELIB_ZONETYPE_ABBR) { + free(intern->tzi.z.abbr); + } zend_object_std_dtor(&intern->std TSRMLS_CC); efree(object); } @@ -1660,7 +1705,9 @@ timelib_time *now; timelib_tzinfo *tzi; timelib_error_container *err = NULL; - int free_tzi = 0; + int free_tzi = 0, type = TIMELIB_ZONETYPE_ID, new_dst; + char *new_abbr; + timelib_sll new_offset; if (dateobj->time) { if (dateobj->time->tz_info) { @@ -1681,8 +1728,21 @@ php_timezone_obj *tzobj; tzobj = (php_timezone_obj *) zend_object_store_get_object(timezone_object TSRMLS_CC); - tzi = timelib_tzinfo_clone(tzobj->tz); - free_tzi = 1; + switch (tzobj->type) { + case TIMELIB_ZONETYPE_ID: + tzi = timelib_tzinfo_clone(tzobj->tzi.tz); + free_tzi = 1; + break; + case TIMELIB_ZONETYPE_OFFSET: + new_offset = tzobj->tzi.utc_offset; + break; + case TIMELIB_ZONETYPE_ABBR: + new_offset = tzobj->tzi.z.utc_offset; + new_dst = tzobj->tzi.z.dst; + new_abbr = strdup(tzobj->tzi.z.abbr); + break; + } + type = tzobj->type; } else if (dateobj->time->tz_info) { tzi = timelib_tzinfo_clone(dateobj->time->tz_info); free_tzi = 1; @@ -1691,8 +1751,20 @@ } now = timelib_time_ctor(); - now->tz_info = tzi; - now->zone_type = TIMELIB_ZONETYPE_ID; + now->zone_type = type; + switch (type) { + case TIMELIB_ZONETYPE_ID: + now->tz_info = tzi; + break; + case TIMELIB_ZONETYPE_OFFSET: + now->z = new_offset; + break; + case TIMELIB_ZONETYPE_ABBR: + now->z = new_offset; + now->dst = new_dst; + now->tz_abbr = new_abbr; + break; + } timelib_unixtime2local(now, (timelib_sll) time(NULL)); timelib_fill_holes(dateobj->time, now, 0); @@ -1700,7 +1772,7 @@ dateobj->time->have_weekday_relative = dateobj->time->have_relative = 0; - if (now->tz_info != tzi) { + if (type == TIMELIB_ZONETYPE_ID && now->tz_info != tzi) { timelib_tzinfo_dtor(now->tz_info); } if (free_tzi) { @@ -1977,10 +2049,23 @@ } dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); DATE_CHECK_INITIALIZED(dateobj->time, DateTime); - if (dateobj->time->is_localtime && dateobj->time->tz_info) { + if (dateobj->time->is_localtime/* && dateobj->time->tz_info*/) { date_instantiate(date_ce_timezone, return_value TSRMLS_CC); tzobj = (php_timezone_obj *) zend_object_store_get_object(return_value TSRMLS_CC); - tzobj->tz = timelib_tzinfo_clone(dateobj->time->tz_info); + tzobj->type = dateobj->time->zone_type; + switch (dateobj->time->zone_type) { + case TIMELIB_ZONETYPE_ID: + tzobj->tzi.tz = dateobj->time->tz_info; + break; + case TIMELIB_ZONETYPE_OFFSET: + tzobj->tzi.utc_offset = dateobj->time->z; + break; + case TIMELIB_ZONETYPE_ABBR: + tzobj->tzi.z.utc_offset = dateobj->time->z; + tzobj->tzi.z.dst = dateobj->time->dst; + tzobj->tzi.z.abbr = strdup(dateobj->time->tz_abbr); + break; + } } else { RETURN_FALSE; } @@ -2003,10 +2088,13 @@ dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); DATE_CHECK_INITIALIZED(dateobj->time, DateTime); tzobj = (php_timezone_obj *) zend_object_store_get_object(timezone_object TSRMLS_CC); + if (tzobj->type != TIMELIB_ZONETYPE_ID) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only do this for zones with ID for now"); + } if (dateobj->time->tz_info) { timelib_tzinfo_dtor(dateobj->time->tz_info); } - timelib_set_timezone(dateobj->time, timelib_tzinfo_clone(tzobj->tz)); + timelib_set_timezone(dateobj->time, timelib_tzinfo_clone(tzobj->tzi.tz)); timelib_unixtime2local(dateobj->time, dateobj->time->sse); } /* }}} */ @@ -2025,10 +2113,20 @@ } dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); DATE_CHECK_INITIALIZED(dateobj->time, DateTime); - if (dateobj->time->is_localtime && dateobj->time->tz_info) { - offset = timelib_get_time_zone_info(dateobj->time->sse, dateobj->time->tz_info); - RETVAL_LONG(offset->offset); - timelib_time_offset_dtor(offset); + if (dateobj->time->is_localtime/* && dateobj->time->tz_info*/) { + switch (dateobj->time->zone_type) { + case TIMELIB_ZONETYPE_ID: + offset = timelib_get_time_zone_info(dateobj->time->sse, dateobj->time->tz_info); + RETVAL_LONG(offset->offset); + timelib_time_offset_dtor(offset); + break; + case TIMELIB_ZONETYPE_OFFSET: + RETVAL_LONG(dateobj->time->z * -60); + break; + case TIMELIB_ZONETYPE_ABBR: + RETVAL_LONG((dateobj->time->z - (60 * dateobj->time->dst)) * -60); + break; + } return; } else { RETURN_LONG(0); @@ -2149,6 +2247,7 @@ char *tz; int tz_len; timelib_tzinfo *tzi = NULL; + php_timezone_obj *tzobj; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tz, &tz_len) == FAILURE) { RETURN_FALSE; @@ -2156,7 +2255,9 @@ if (SUCCESS != timezone_initialize(&tzi, tz TSRMLS_CC)) { RETURN_FALSE; } - ((php_timezone_obj *) zend_object_store_get_object(date_instantiate(date_ce_timezone, return_value TSRMLS_CC) TSRMLS_CC))->tz = tzi; + tzobj = zend_object_store_get_object(date_instantiate(date_ce_timezone, return_value TSRMLS_CC) TSRMLS_CC); + tzobj->type = TIMELIB_ZONETYPE_ID; + tzobj->tzi.tz = tzi; } /* }}} */ @@ -2168,11 +2269,14 @@ char *tz; int tz_len; timelib_tzinfo *tzi = NULL; + php_timezone_obj *tzobj; php_set_error_handling(EH_THROW, NULL TSRMLS_CC); if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tz, &tz_len)) { if (SUCCESS == timezone_initialize(&tzi, tz TSRMLS_CC)) { - ((php_timezone_obj *) zend_object_store_get_object(getThis() TSRMLS_CC))->tz = tzi; + tzobj = zend_object_store_get_object(getThis() TSRMLS_CC); + tzobj->type = TIMELIB_ZONETYPE_ID; + tzobj->tzi.tz = tzi; } else { ZVAL_NULL(getThis()); } @@ -2193,9 +2297,28 @@ RETURN_FALSE; } tzobj = (php_timezone_obj *) zend_object_store_get_object(object TSRMLS_CC); - DATE_CHECK_INITIALIZED(tzobj->tz, DateTimeZone); + DATE_CHECK_INITIALIZED(tzobj->tzi.tz, DateTimeZone); - RETURN_STRING(tzobj->tz->name, 1); + switch (tzobj->type) { + case TIMELIB_ZONETYPE_ID: + RETURN_STRING(tzobj->tzi.tz->name, 1); + break; + case TIMELIB_ZONETYPE_OFFSET: { + char *tmpstr = emalloc(sizeof("UTC+05:00")); + timelib_sll utc_offset = tzobj->tzi.utc_offset; + + snprintf(tmpstr, sizeof("+05:00"), "%c%02d:%02d", + utc_offset > 0 ? '-' : '+', + abs(utc_offset / 60), + abs((utc_offset % 60))); + + RETURN_STRING(tmpstr, 0); + } + break; + case TIMELIB_ZONETYPE_ABBR: + RETURN_STRING(tzobj->tzi.z.abbr, 1); + break; + } } /* }}} */ @@ -2237,11 +2360,11 @@ RETURN_FALSE; } tzobj = (php_timezone_obj *) zend_object_store_get_object(object TSRMLS_CC); - DATE_CHECK_INITIALIZED(tzobj->tz, DateTimeZone); + DATE_CHECK_INITIALIZED(tzobj->tzi.tz, DateTimeZone); dateobj = (php_date_obj *) zend_object_store_get_object(dateobject TSRMLS_CC); DATE_CHECK_INITIALIZED(dateobj->time, DateTime); - offset = timelib_get_time_zone_info(dateobj->time->sse, tzobj->tz); + offset = timelib_get_time_zone_info(dateobj->time->sse, tzobj->tzi.tz); RETVAL_LONG(offset->offset); timelib_time_offset_dtor(offset); } @@ -2260,17 +2383,20 @@ RETURN_FALSE; } tzobj = (php_timezone_obj *) zend_object_store_get_object(object TSRMLS_CC); - DATE_CHECK_INITIALIZED(tzobj->tz, DateTimeZone); + DATE_CHECK_INITIALIZED(tzobj->tzi.tz, DateTimeZone); + if (tzobj->type != TIMELIB_ZONETYPE_ID) { + RETURN_FALSE; + } array_init(return_value); - for (i = 0; i < tzobj->tz->timecnt; ++i) { + for (i = 0; i < tzobj->tzi.tz->timecnt; ++i) { MAKE_STD_ZVAL(element); array_init(element); - add_assoc_long(element, "ts", tzobj->tz->trans[i]); - add_assoc_string(element, "time", php_format_date(DATE_FORMAT_ISO8601, 13, tzobj->tz->trans[i], 0 TSRMLS_CC), 0); - add_assoc_long(element, "offset", tzobj->tz->type[tzobj->tz->trans_idx[i]].offset); - add_assoc_bool(element, "isdst", tzobj->tz->type[tzobj->tz->trans_idx[i]].isdst); - add_assoc_string(element, "abbr", &tzobj->tz->timezone_abbr[tzobj->tz->type[tzobj->tz->trans_idx[i]].abbr_idx], 1); + add_assoc_long(element, "ts", tzobj->tzi.tz->trans[i]); + add_assoc_string(element, "time", php_format_date(DATE_FORMAT_ISO8601, 13, tzobj->tzi.tz->trans[i], 0 TSRMLS_CC), 0); + add_assoc_long(element, "offset", tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].offset); + add_assoc_bool(element, "isdst", tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].isdst); + add_assoc_string(element, "abbr", &tzobj->tzi.tz->timezone_abbr[tzobj->tzi.tz->type[tzobj->tzi.tz->trans_idx[i]].abbr_idx], 1); add_next_index_zval(return_value, element); } http://cvs.php.net/viewvc.cgi/php-src/ext/date/lib/parse_date.c?r1=1.29.2.30.2.14.2.1&r2=1.29.2.30.2.14.2.2&diff_format=u Index: php-src/ext/date/lib/parse_date.c diff -u php-src/ext/date/lib/parse_date.c:1.29.2.30.2.14.2.1 php-src/ext/date/lib/parse_date.c:1.29.2.30.2.14.2.2 --- php-src/ext/date/lib/parse_date.c:1.29.2.30.2.14.2.1 Sun Jan 13 15:15:48 2008 +++ php-src/ext/date/lib/parse_date.c Thu Jan 17 18:49:31 2008 @@ -1,4 +1,4 @@ -/* Generated by re2c 0.12.1 on Sun Jan 13 15:46:00 2008 */ +/* Generated by re2c 0.12.1 on Thu Jan 17 09:50:31 2008 */ #line 1 "ext/date/lib/parse_date.re" /* +----------------------------------------------------------------------+ @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: parse_date.c,v 1.29.2.30.2.14.2.1 2008/01/13 15:15:48 derick Exp $ */ +/* $Id: parse_date.c,v 1.29.2.30.2.14.2.2 2008/01/17 18:49:31 derick Exp $ */ #include "timelib.h" http://cvs.php.net/viewvc.cgi/php-src/ext/date/tests/bug40743.phpt?view=markup&rev=1.1 Index: php-src/ext/date/tests/bug40743.phpt +++ php-src/ext/date/tests/bug40743.phpt --TEST-- Bug #40743 (DateTime ignores the TimeZone object passed to the constructor) --FILE-- <?php $dt = new DateTime('@1200506699', new DateTimeZone('Europe/Berlin')); echo $dt->format(DATE_RFC822), "\n"; echo $dt->format('T e Z'), "\n"; echo "-----\n"; date_default_timezone_set('America/New_York'); $dt = new DateTime('16 Jan 08 13:04:59'); echo $dt->format(DATE_RFC822 . " e T O U"), "\n"; $dt = new DateTime('@1200506699'); echo $dt->format(DATE_RFC822 . " e T O U"), "\n"; $dt = new DateTime('@1200506699'); $dt->setTimezone( new DateTimeZone( 'America/New_York' ) ); echo $dt->format(DATE_RFC822 . " e T O U"), "\n"; $dt = new DateTime('@1200506699', new DateTimeZone('Europe/Berlin')); echo $dt->format(DATE_RFC822 . " e T O U"), "\n"; $dt = new DateTime('16 Jan 08 13:04:59 America/Chicago'); echo $dt->format(DATE_RFC822 . " e T O U"), "\n"; $dt = new DateTime('16 Jan 08 13:04:59 America/Chicago', new DateTimeZone('Europe/Berlin')); echo $dt->format(DATE_RFC822 . " e T O U"), "\n"; ?> --EXPECT-- Wed, 16 Jan 08 18:04:59 +0000 GMT+0000 +00:00 0 ----- Wed, 16 Jan 08 13:04:59 -0500 America/New_York EST -0500 1200506699 Wed, 16 Jan 08 18:04:59 +0000 +00:00 GMT+0000 +0000 1200506699 Wed, 16 Jan 08 13:04:59 -0500 America/New_York EST -0500 1200506699 Wed, 16 Jan 08 18:04:59 +0000 +00:00 GMT+0000 +0000 1200506699 Wed, 16 Jan 08 13:04:59 -0600 America/Chicago CST -0600 1200510299 Wed, 16 Jan 08 13:04:59 -0600 America/Chicago CST -0600 1200510299 http://cvs.php.net/viewvc.cgi/php-src/ext/date/tests/bug42910.phpt?view=markup&rev=1.1 Index: php-src/ext/date/tests/bug42910.phpt +++ php-src/ext/date/tests/bug42910.phpt --TEST-- Bug #42910 (Constructing DateTime with TimeZone Indicator invalidates DateTimeZone) --FILE-- <?php date_default_timezone_set('America/Los_Angeles'); $foo = new DateTime('2007-03-11'); $bar = new DateTime('2007-03-11T00:00:00-0800'); print $foo->format(DateTime::ISO8601) . ' - ' . $foo->getTimezone()->getName() . ' - ' . $foo->format('U') . "\r\n"; print $bar->format(DateTime::ISO8601) . ' - ' . $bar->getTimezone()->getName() . ' - ' . $bar->format('U') . "\r\n"; $foo->setDate(2007, 03, 12); $bar->setDate(2007, 03, 12); print $foo->format(DateTime::ISO8601) . ' - ' . $foo->getTimezone()->getName() . ' - ' . $foo->format('U') . "\r\n"; print $bar->format(DateTime::ISO8601) . ' - ' . $bar->getTimezone()->getName() . ' - ' . $bar->format('U') . "\r\n"; // -------------- date_default_timezone_set('Australia/Sydney'); $date= date_create('2007-11-04 12:00:00+0200'); var_dump(date_format($date, 'O e')); ?> --EXPECT-- 2007-03-11T00:00:00-0800 - America/Los_Angeles - 1173600000 2007-03-11T00:00:00-0800 - -08:00 - 1173600000 2007-03-12T00:00:00-0700 - America/Los_Angeles - 1173682800 2007-03-12T00:00:00-0800 - -08:00 - 1173686400 string(12) "+0200 +02:00" --UEXPECT-- 2007-03-11T00:00:00-0800 - America/Los_Angeles - 1173600000 2007-03-11T00:00:00-0800 - -08:00 - 1173600000 2007-03-12T00:00:00-0700 - America/Los_Angeles - 1173682800 2007-03-12T00:00:00-0800 - -08:00 - 1173686400 unicode(12) "+0200 +02:00" http://cvs.php.net/viewvc.cgi/php-src/ext/date/tests/bug43527.phpt?view=markup&rev=1.1 Index: php-src/ext/date/tests/bug43527.phpt +++ php-src/ext/date/tests/bug43527.phpt --TEST-- Bug #43527 (DateTime created from a timestamp reports environment timezone) --FILE-- <?php date_default_timezone_set("Etc/GMT+1"); $datetime = new DateTime('Fri, 07 Dec 2007 19:05:14 +1000'); echo $datetime->getTimezone()->getName(), "\n"; ?> --EXPECT-- +10:00
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php