From c2e11f077625c22ede1455e5d4fbb26afa884ac9 Mon Sep 17 00:00:00 2001 From: Lonny Kapelushnik Date: Wed, 14 Nov 2012 05:04:46 +0000 Subject: [PATCH] Made separate tests for each TZ type Fixed handling of unserializing types 1 and 3 --- ext/date/lib/parse_date.re | 66 +++++++++---------- ext/date/lib/timelib.h | 1 + ext/date/php_date.c | 31 +++++---- .../tests/DateTimeZone_serialize_type_1.phpt | 35 ++++++++++ .../tests/DateTimeZone_serialize_type_2.phpt | 35 ++++++++++ ...hpt => DateTimeZone_serialize_type_3.phpt} | 0 6 files changed, 124 insertions(+), 44 deletions(-) create mode 100644 ext/date/tests/DateTimeZone_serialize_type_1.phpt create mode 100644 ext/date/tests/DateTimeZone_serialize_type_2.phpt rename ext/date/tests/{DateTimeZone_serialize.phpt => DateTimeZone_serialize_type_3.phpt} (100%) diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re index 8e1972d99f106..06ab7e36bb9c2 100644 --- a/ext/date/lib/parse_date.re +++ b/ext/date/lib/parse_date.re @@ -530,39 +530,6 @@ static timelib_ull timelib_get_unsigned_nr(char **ptr, int max_length) return dir * timelib_get_nr(ptr, max_length); } -static long timelib_parse_tz_cor(char **ptr) -{ - char *begin = *ptr, *end; - long tmp; - - while (isdigit(**ptr) || **ptr == ':') { - ++*ptr; - } - end = *ptr; - switch (end - begin) { - case 1: - case 2: - return HOUR(strtol(begin, NULL, 10)); - break; - case 3: - case 4: - if (begin[1] == ':') { - tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 2, NULL, 10); - return tmp; - } else if (begin[2] == ':') { - tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10); - return tmp; - } else { - tmp = strtol(begin, NULL, 10); - return HOUR(tmp / 100) + tmp % 100; - } - case 5: - tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10); - return tmp; - } - return 0; -} - static timelib_sll timelib_lookup_relative_text(char **ptr, int *behavior) { char *word; @@ -2271,6 +2238,39 @@ const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void) return timelib_timezone_lookup; } +long timelib_parse_tz_cor(char **ptr) +{ + char *begin = *ptr, *end; + long tmp; + + while (isdigit(**ptr) || **ptr == ':') { + ++*ptr; + } + end = *ptr; + switch (end - begin) { + case 1: + case 2: + return HOUR(strtol(begin, NULL, 10)); + break; + case 3: + case 4: + if (begin[1] == ':') { + tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 2, NULL, 10); + return tmp; + } else if (begin[2] == ':') { + tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10); + return tmp; + } else { + tmp = strtol(begin, NULL, 10); + return HOUR(tmp / 100) + tmp % 100; + } + case 5: + tmp = HOUR(strtol(begin, NULL, 10)) + strtol(begin + 3, NULL, 10); + return tmp; + } + return 0; +} + #ifdef DEBUG_PARSER_STUB int main(void) { diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h index 478dec32d04b8..d941cf6d0864f 100644 --- a/ext/date/lib/timelib.h +++ b/ext/date/lib/timelib.h @@ -73,6 +73,7 @@ timelib_time *timelib_parse_from_format(char *format, char *s, int len, timelib_ void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options); char *timelib_timezone_id_from_abbr(const char *abbr, long gmtoffset, int isdst); const timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void); +long timelib_parse_tz_cor(char**); /* From parse_iso_intervals.re */ void timelib_strtointerval(char *s, int len, diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 0ea28ec7d0329..9be0ae640cfdd 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -2210,15 +2210,15 @@ static HashTable *date_object_get_properties_timezone(zval *object TSRMLS_DC) char *tmpstr = emalloc(sizeof("UTC+05:00")); snprintf(tmpstr, sizeof("+05:00"), "%c%02d:%02d", - tzobj->tzi.z.utc_offset > 0 ? '-' : '+', - abs(tzobj->tzi.z.utc_offset / 60), - abs((tzobj->tzi.z.utc_offset % 60))); + tzobj->tzi.utc_offset > 0 ? '-' : '+', + abs(tzobj->tzi.utc_offset / 60), + abs((tzobj->tzi.utc_offset % 60))); ZVAL_STRING(zv, tmpstr, 0); } break; case TIMELIB_ZONETYPE_ABBR: - ZVAL_STRING(zv, tzobj->tzi.tz->timezone_abbr, 1); + ZVAL_STRING(zv, tzobj->tzi.z.abbr, 1); break; } zend_hash_update(props, "timezone", 9, &zv, sizeof(zval), NULL); @@ -3294,30 +3294,39 @@ static int php_date_timezone_initialize_from_hash(zval **return_value, php_timez zval **z_timezone = NULL; zval **z_timezone_type = NULL; timelib_tzinfo *tzi; + char **offset; if (zend_hash_find(myht, "timezone_type", 14, (void**) &z_timezone_type) == SUCCESS) { if (zend_hash_find(myht, "timezone", 9, (void**) &z_timezone) == SUCCESS) { convert_to_long(*z_timezone_type); switch (Z_LVAL_PP(z_timezone_type)) { case TIMELIB_ZONETYPE_OFFSET: + offset = malloc(sizeof(char) * (Z_STRLEN_PP(z_timezone) + 1)); + *offset = (Z_STRVAL_PP(z_timezone)); + if(**offset == '+'){ + ++*offset; + (*tzobj)->tzi.utc_offset = -1 * timelib_parse_tz_cor((char **)offset); + } else { + ++*offset; + (*tzobj)->tzi.utc_offset = timelib_parse_tz_cor((char **)offset); + } + free(offset); (*tzobj)->type = TIMELIB_ZONETYPE_OFFSET; - (*tzobj)->tzi.utc_offset = Z_LVAL_PP(z_timezone); + (*tzobj)->initialized = 1; + return SUCCESS; break; case TIMELIB_ZONETYPE_ABBR: - (*tzobj)->type = TIMELIB_ZONETYPE_ABBR; - (*tzobj)->tzi.z.utc_offset = Z_LVAL_PP(z_timezone); - break; case TIMELIB_ZONETYPE_ID: if (SUCCESS == timezone_initialize(&tzi, Z_STRVAL_PP(z_timezone) TSRMLS_CC)) { (*tzobj)->type = TIMELIB_ZONETYPE_ID; (*tzobj)->tzi.tz = tzi; (*tzobj)->initialized = 1; - return 1; + return SUCCESS; } } } } - return 0; + return FAILURE; } /* {{{ proto DateTimeZone::__set_state() @@ -3351,7 +3360,7 @@ PHP_METHOD(DateTimeZone, __wakeup) tzobj = (php_timezone_obj *) zend_object_store_get_object(object TSRMLS_CC); myht = Z_OBJPROP_P(object); - + php_date_timezone_initialize_from_hash(&return_value, &tzobj, myht TSRMLS_CC); } /* }}} */ diff --git a/ext/date/tests/DateTimeZone_serialize_type_1.phpt b/ext/date/tests/DateTimeZone_serialize_type_1.phpt new file mode 100644 index 0000000000000..51a5c53b234aa --- /dev/null +++ b/ext/date/tests/DateTimeZone_serialize_type_1.phpt @@ -0,0 +1,35 @@ +--TEST-- +Test serialization of DateTimeZone objects +--FILE-- +getTimezone(); +var_dump( $tz1 ); +$serialized = serialize($tz1); +var_dump($serialized); + +$tz2 = unserialize($serialized); +var_dump($tz2); +// Try to use unserialzied object +var_dump( $tz2->getName() ); + +?> +===DONE=== +--EXPECTF-- +object(DateTimeZone)#%d (2) { + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "+01:00" +} +string(77) "O:12:"DateTimeZone":2:{s:13:"timezone_type";i:1;s:8:"timezone";s:6:"+01:00";}" +object(DateTimeZone)#%d (2) { + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "+01:00" +} +string(6) "+01:00" +===DONE=== diff --git a/ext/date/tests/DateTimeZone_serialize_type_2.phpt b/ext/date/tests/DateTimeZone_serialize_type_2.phpt new file mode 100644 index 0000000000000..a264322f3e18e --- /dev/null +++ b/ext/date/tests/DateTimeZone_serialize_type_2.phpt @@ -0,0 +1,35 @@ +--TEST-- +Test serialization of DateTimeZone objects +--FILE-- +getName() ); + +?> +===DONE=== +--EXPECTF-- +object(DateTimeZone)#%d (2) { + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "America/New_York" +} +string(88) "O:12:"DateTimeZone":2:{s:13:"timezone_type";i:3;s:8:"timezone";s:16:"America/New_York";}" +object(DateTimeZone)#%d (2) { + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(16) "America/New_York" +} +string(16) "America/New_York" +===DONE=== diff --git a/ext/date/tests/DateTimeZone_serialize.phpt b/ext/date/tests/DateTimeZone_serialize_type_3.phpt similarity index 100% rename from ext/date/tests/DateTimeZone_serialize.phpt rename to ext/date/tests/DateTimeZone_serialize_type_3.phpt