Sorry for the double message, still getting used to doing patches instead of applying changes directly. I accidentally attached an old patch file, not the latest. The previous had a bug in php_date_initialize() which I caught in my testing (I left the local variable tzi, by mistake, instead of using now->tz_info), but didn't regenerate the patch file. Caught up upon reviewing the patch itself and realizing it was the old one. :-/
Attached is the proper patch, thanks.
diff --git a/ext/date/php_date.c b/ext/date/php_date.c index b588227..c1c53cf 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -526,7 +526,7 @@ static zend_object_handlers date_object_handlers_period; #define DATE_SET_CONTEXT \ zval *object; \ object = getThis(); \ - + #define DATE_FETCH_OBJECT \ php_date_obj *obj; \ DATE_SET_CONTEXT; \ @@ -688,7 +688,7 @@ PHP_RSHUTDOWN_FUNCTION(date) * RFC2822, Section 3.3: http://www.ietf.org/rfc/rfc2822.txt * FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space * CFWS = *([FWS] comment) (([FWS] comment) / FWS) - * + * * date-time = [ day-of-week "," ] date FWS time [CFWS] * day-of-week = ([FWS] day-name) * day-name = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun" @@ -710,19 +710,19 @@ PHP_RSHUTDOWN_FUNCTION(date) * date-fullyear = 4DIGIT * date-month = 2DIGIT ; 01-12 * date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year - * + * * time-hour = 2DIGIT ; 00-23 * time-minute = 2DIGIT ; 00-59 * time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules - * + * * time-secfrac = "." 1*DIGIT * time-numoffset = ("+" / "-") time-hour ":" time-minute * time-offset = "Z" / time-numoffset - * + * * partial-time = time-hour ":" time-minute ":" time-second [time-secfrac] * full-date = date-fullyear "-" date-month "-" date-mday * full-time = partial-time time-offset - * + * * date-time = full-date "T" full-time */ #define DATE_FORMAT_RFC3339 "Y-m-d\\TH:i:sP" @@ -804,7 +804,7 @@ PHP_MSHUTDOWN_FUNCTION(date) PHP_MINFO_FUNCTION(date) { const timelib_tzdb *tzdb = DATE_TIMEZONEDB; - + php_info_print_table_start(); php_info_print_table_row(2, "date/time support", "enabled"); php_info_print_table_row(2, "\"Olson\" Timezone Database Version", tzdb->version); @@ -855,7 +855,7 @@ static char* guess_timezone(const timelib_tzdb *tzdb TSRMLS_DC) if (!DATEG(default_timezone)) { /* Special case: ext/date wasn't initialized yet */ zval ztz; - + if (SUCCESS == zend_get_configuration_directive("date.timezone", sizeof("date.timezone"), &ztz) && Z_TYPE(ztz) == IS_STRING && Z_STRLEN(ztz) > 0 && @@ -936,8 +936,8 @@ char *php_date_short_day_name(timelib_sll y, timelib_sll m, timelib_sll d) timelib_sll day_of_week = timelib_day_of_week(y, m, d); if (day_of_week < 0) { return "Unknown"; - } - return day_short_names[day_of_week]; + } + return day_short_names[day_of_week]; } /* }}} */ @@ -950,7 +950,7 @@ static char *date_format(char *format, int format_len, timelib_time *t, int loca timelib_time_offset *offset = NULL; timelib_sll isoweek, isoyear; int rfc_colon; - int weekYearSet = 0; + int week_year_set = 0; if (!format_len) { return estrdup(""); @@ -969,7 +969,7 @@ static char *date_format(char *format, int format_len, timelib_time *t, int loca offset->leap_secs = 0; offset->is_dst = 0; offset->abbr = malloc(9); /* GMT�xxxx\0 */ - snprintf(offset->abbr, 9, "GMT%c%02d%02d", + 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 ); @@ -993,11 +993,17 @@ static char *date_format(char *format, int format_len, timelib_time *t, int loca /* week */ case 'W': - if(!weekYearSet) { timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); weekYearSet = 1; } - length = slprintf(buffer, 32, "%02d", (int) isoweek); break; /* iso weeknr */ case 'o': - if(!weekYearSet) { timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); weekYearSet = 1; } - length = slprintf(buffer, 32, "%d", (int) isoyear); break; /* iso year */ + if (!week_year_set) { + timelib_isoweek_from_date(t->y, t->m, t->d, &isoweek, &isoyear); + week_year_set = 1; + } + if (format[i]=='W') { + length = slprintf(buffer, 32, "%02d", (int) isoweek); /* iso weeknr */ + } else if (format[i]=='o') { + length = slprintf(buffer, 32, "%d", (int) isoyear); /* iso year */ + } + break; /* month */ case 'F': length = slprintf(buffer, 32, "%s", mon_full_names[t->m - 1]); break; @@ -1015,7 +1021,7 @@ static char *date_format(char *format, int format_len, timelib_time *t, int loca case 'a': length = slprintf(buffer, 32, "%s", t->h >= 12 ? "pm" : "am"); break; case 'A': length = slprintf(buffer, 32, "%s", t->h >= 12 ? "PM" : "AM"); break; case 'B': { - int retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864); + int retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864); while (retval < 0) { retval += 1000; } @@ -1115,7 +1121,7 @@ static void php_date(INTERNAL_FUNCTION_PARAMETERS, int localtime) } string = php_format_date(format, format_len, ts, localtime TSRMLS_CC); - + RETVAL_STRING(string, 0); } /* }}} */ @@ -1139,7 +1145,7 @@ PHPAPI char *php_format_date(char *format, int format_len, time_t ts, int localt } string = date_format(format, format_len, t, localtime); - + timelib_time_dtor(t); return string; } @@ -1180,7 +1186,7 @@ PHPAPI int php_idate(char format, time_t ts, int localtime TSRMLS_DC) offset->leap_secs = 0; offset->is_dst = t->dst; offset->abbr = malloc(9); /* GMT�xxxx\0 */ - snprintf(offset->abbr, 9, "GMT%c%02d%02d", + 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 ); @@ -1212,7 +1218,7 @@ PHPAPI int php_idate(char format, time_t ts, int localtime TSRMLS_DC) /* Swatch Beat a.k.a. Internet Time */ case 'B': - retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864); + retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864); while (retval < 0) { retval += 1000; } @@ -1264,7 +1270,7 @@ PHP_FUNCTION(idate) char *format; int format_len; long ts = 0; - int ret; + int ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &format, &format_len, &ts) == FAILURE) { RETURN_FALSE; @@ -1292,7 +1298,7 @@ PHP_FUNCTION(idate) PHPAPI void php_date_set_tzdb(timelib_tzdb *tzdb) { const timelib_tzdb *builtin = timelib_builtin_db(); - + if (php_version_compare(tzdb->version, builtin->version) > 0) { php_date_global_timezone_db = tzdb; php_date_global_timezone_db_enabled = 1; @@ -1804,7 +1810,7 @@ static void date_period_it_current_data(zend_object_iterator *iter, zval ***data if (it_time->tz_info) { newdateobj->time->tz_info = it_time->tz_info; } - + *data = &iterator->current; } /* }}} */ @@ -1967,13 +1973,13 @@ static inline zend_object_value date_object_new_date_ex(zend_class_entry *class_ if (ptr) { *ptr = intern; } - + zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_date, NULL TSRMLS_CC); retval.handlers = &date_object_handlers_date; - + return retval; } @@ -1987,12 +1993,12 @@ static zend_object_value date_object_clone_date(zval *this_ptr TSRMLS_DC) php_date_obj *new_obj = NULL; php_date_obj *old_obj = (php_date_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC); zend_object_value new_ov = date_object_new_date_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); if (!old_obj->time) { return new_ov; } - + /* this should probably moved to a new `timelib_time *timelime_time_clone(timelib_time *)` */ new_obj->time = timelib_time_ctor(); *new_obj->time = *old_obj->time; @@ -2002,7 +2008,7 @@ static zend_object_value date_object_clone_date(zval *this_ptr TSRMLS_DC) if (old_obj->time->tz_info) { new_obj->time->tz_info = old_obj->time->tz_info; } - + return new_ov; } @@ -2013,17 +2019,17 @@ static int date_object_compare_date(zval *d1, zval *d2 TSRMLS_DC) instanceof_function(Z_OBJCE_P(d2), date_ce_date TSRMLS_CC)) { php_date_obj *o1 = zend_object_store_get_object(d1 TSRMLS_CC); php_date_obj *o2 = zend_object_store_get_object(d2 TSRMLS_CC); - + if (!o1->time->sse_uptodate) { timelib_update_ts(o1->time, o1->time->tz_info); } if (!o2->time->sse_uptodate) { timelib_update_ts(o2->time, o2->time->tz_info); } - + return (o1->time->sse == o2->time->sse) ? 0 : ((o1->time->sse < o2->time->sse) ? -1 : 1); } - + return 1; } @@ -2100,10 +2106,10 @@ static inline zend_object_value date_object_new_timezone_ex(zend_class_entry *cl zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_timezone, NULL TSRMLS_CC); retval.handlers = &date_object_handlers_timezone; - + return retval; } @@ -2117,12 +2123,12 @@ static zend_object_value date_object_clone_timezone(zval *this_ptr TSRMLS_DC) php_timezone_obj *new_obj = NULL; php_timezone_obj *old_obj = (php_timezone_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC); 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); if (!old_obj->initialized) { return new_ov; } - + new_obj->type = old_obj->type; new_obj->initialized = 1; switch (new_obj->type) { @@ -2138,7 +2144,7 @@ static zend_object_value date_object_clone_timezone(zval *this_ptr TSRMLS_DC) new_obj->tzi.z.abbr = old_obj->tzi.z.abbr; break; } - + return new_ov; } @@ -2155,10 +2161,10 @@ static inline zend_object_value date_object_new_interval_ex(zend_class_entry *cl zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_interval, NULL TSRMLS_CC); retval.handlers = &date_object_handlers_interval; - + return retval; } @@ -2172,7 +2178,7 @@ static zend_object_value date_object_clone_interval(zval *this_ptr TSRMLS_DC) php_interval_obj *new_obj = NULL; php_interval_obj *old_obj = (php_interval_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC); zend_object_value new_ov = date_object_new_interval_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); /** FIX ME ADD CLONE STUFF **/ @@ -2238,10 +2244,10 @@ static inline zend_object_value date_object_new_period_ex(zend_class_entry *clas zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_period, NULL TSRMLS_CC); retval.handlers = &date_object_handlers_period; - + return retval; } @@ -2255,7 +2261,7 @@ static zend_object_value date_object_clone_period(zval *this_ptr TSRMLS_DC) php_period_obj *new_obj = NULL; php_period_obj *old_obj = (php_period_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC); zend_object_value new_ov = date_object_new_period_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); /** FIX ME ADD CLONE STUFF **/ @@ -2339,12 +2345,8 @@ static void update_errors_warnings(timelib_error_container *last_errors TSRMLS_D PHPAPI int php_date_initialize(php_date_obj *dateobj, /*const*/ char *time_str, int time_str_len, char *format, zval *timezone_object, int ctor TSRMLS_DC) { timelib_time *now; - timelib_tzinfo *tzi = NULL; timelib_error_container *err = NULL; - int type = TIMELIB_ZONETYPE_ID, new_dst; - char *new_abbr; - timelib_sll new_offset; - + if (dateobj->time) { timelib_time_dtor(dateobj->time); } @@ -2367,49 +2369,38 @@ PHPAPI int php_date_initialize(php_date_obj *dateobj, /*const*/ char *time_str, return 0; } + now = timelib_time_ctor(); if (timezone_object) { php_timezone_obj *tzobj; tzobj = (php_timezone_obj *) zend_object_store_get_object(timezone_object TSRMLS_CC); switch (tzobj->type) { case TIMELIB_ZONETYPE_ID: - tzi = tzobj->tzi.tz; + now->tz_info = tzobj->tzi.tz; break; case TIMELIB_ZONETYPE_OFFSET: - new_offset = tzobj->tzi.utc_offset; + now->z = 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); + now->z = tzobj->tzi.z.utc_offset; + now->dst = tzobj->tzi.z.dst; + now->tz_abbr = strdup(tzobj->tzi.z.abbr); break; } - type = tzobj->type; - } else if (dateobj->time->tz_info) { - tzi = dateobj->time->tz_info; + now->zone_type = tzobj->type; } else { - tzi = get_timezone_info(TSRMLS_C); + now->zone_type = TIMELIB_ZONETYPE_ID; + if (dateobj->time->tz_info) { + now->tz_info = dateobj->time->tz_info; + } else { + now->tz_info = get_timezone_info(TSRMLS_C); + } } - now = timelib_time_ctor(); - 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, TIMELIB_NO_CLONE); - timelib_update_ts(dateobj->time, tzi); + timelib_update_ts(dateobj->time, now->tz_info); dateobj->time->have_relative = 0; @@ -2613,7 +2604,7 @@ void php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAMETERS, timelib_time * PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(hour, h); PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(minute, i); PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(second, s); - + if (parsed_time->f == -99999) { add_assoc_bool(return_value, "fraction", 0); } else { @@ -2680,7 +2671,7 @@ PHP_FUNCTION(date_parse) int date_len; struct timelib_error_container *error; timelib_time *parsed_time; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &date, &date_len) == FAILURE) { RETURN_FALSE; } @@ -2699,7 +2690,7 @@ PHP_FUNCTION(date_parse_from_format) int date_len, format_len; struct timelib_error_container *error; timelib_time *parsed_time; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &format, &format_len, &date, &date_len) == FAILURE) { RETURN_FALSE; } @@ -3052,7 +3043,7 @@ PHP_FUNCTION(date_isodate_set) memset(&dateobj->time->relative, 0, sizeof(dateobj->time->relative)); dateobj->time->relative.d = timelib_daynr_from_weeknr(y, w, d); dateobj->time->have_relative = 1; - + timelib_update_ts(dateobj->time, NULL); RETURN_ZVAL(object, 1, 0); @@ -3139,15 +3130,15 @@ PHP_FUNCTION(date_diff) static int timezone_initialize(timelib_tzinfo **tzi, /*const*/ char *tz TSRMLS_DC) { char *tzid; - + *tzi = NULL; - + if ((tzid = timelib_timezone_id_from_abbr(tz, -1, 0))) { *tzi = php_date_parse_tzfile(tzid, DATE_TIMEZONEDB TSRMLS_CC); } else { *tzi = php_date_parse_tzfile(tz, DATE_TIMEZONEDB TSRMLS_CC); } - + if (*tzi) { return SUCCESS; } else { @@ -3189,7 +3180,7 @@ PHP_METHOD(DateTimeZone, __construct) timelib_tzinfo *tzi = NULL; php_timezone_obj *tzobj; zend_error_handling error_handling; - + zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tz, &tz_len)) { if (SUCCESS == timezone_initialize(&tzi, tz TSRMLS_CC)) { @@ -3416,7 +3407,7 @@ static int date_interval_initialize(timelib_rel_time **rt, /*const*/ char *forma struct timelib_error_container *errors; timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors); - + if (errors->error_count > 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad format (%s)", format); retval = FAILURE; @@ -3571,7 +3562,7 @@ PHP_METHOD(DateInterval, __construct) php_interval_obj *diobj; timelib_rel_time *reltime; zend_error_handling error_handling; - + zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &interval_string, &interval_string_length) == SUCCESS) { if (date_interval_initialize(&reltime, interval_string, interval_string_length TSRMLS_CC) == SUCCESS) { @@ -3767,7 +3758,7 @@ static int date_period_initialize(timelib_time **st, timelib_time **et, timelib_ struct timelib_error_container *errors; timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors); - + if (errors->error_count > 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad format (%s)", format); retval = FAILURE; @@ -3796,7 +3787,7 @@ PHP_METHOD(DatePeriod, __construct) int isostr_len = 0; timelib_time *clone; zend_error_handling error_handling; - + zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "OOl|l", &start, date_ce_date, &interval, date_ce_interval, &recurrences, &options) == FAILURE) { if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "OOO|l", &start, date_ce_date, &interval, date_ce_interval, &end, date_ce_date, &options) == FAILURE) { @@ -3909,7 +3900,7 @@ PHP_FUNCTION(timezone_identifiers_list) tzdb = DATE_TIMEZONEDB; item_count = tzdb->index_size; table = tzdb->index; - + array_init(return_value); for (i = 0; i < item_count; ++i) { @@ -3943,7 +3934,7 @@ PHP_FUNCTION(timezone_abbreviations_list) { const timelib_tz_lookup_table *table, *entry; zval *element, **abbr_array_pp, *abbr_array; - + table = timelib_timezone_abbreviations_list(); array_init(return_value); entry = table; @@ -4019,11 +4010,11 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, int calc_su timelib_time *t; timelib_tzinfo *tzi; char *retstr; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ldddd", &time, &retformat, &latitude, &longitude, &zenith, &gmt_offset) == FAILURE) { RETURN_FALSE; } - + switch (ZEND_NUM_ARGS()) { case 1: retformat = SUNFUNCS_RET_STRING; @@ -4067,7 +4058,7 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, int calc_su timelib_unixtime2local(t, time); rs = timelib_astro_rise_set_altitude(t, longitude, latitude, altitude, 1, &h_rise, &h_set, &rise, &set, &transit); timelib_time_dtor(t); - + if (rs != 0) { RETURN_FALSE; } @@ -4121,7 +4112,7 @@ PHP_FUNCTION(date_sun_info) timelib_sll rise, set, transit; int dummy; double ddummy; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ldd", &time, &latitude, &longitude) == FAILURE) { RETURN_FALSE; } @@ -4135,7 +4126,7 @@ PHP_FUNCTION(date_sun_info) /* Setup */ t2 = timelib_time_ctor(); array_init(return_value); - + /* Get sun up/down and transit */ rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -35.0/60, 1, &ddummy, &ddummy, &rise, &set, &transit); switch (rs) {
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php