mirror of
https://github.com/php/php-src.git
synced 2024-11-24 10:24:11 +08:00
- MFH: Fixed bug #37017 (strtotime fails before 13:00:00 with some time zones
identifiers). (Derick) - MFH: Fixed bug #36988 (mktime freezes on long numbers). (Derick) - MFH: Implemented better error and warning handling that is also used for the date_parse() function. - MFH: Fixed problems with "T" in front of a time string was seen as a time zone string. - MFH: Fixed a problem were 5 and 6 character timezone abbreviations where not correctly parsed. Experimental support (All MFH): - Added the date_parse() function that returns a parsed date/time string including warnings and errors. - Added the timezone_name_from_abbr() function that exposes the guessing mechanism that tries to find a timezone identifier from a timezone abbreviation and GMT offset.
This commit is contained in:
parent
4bab5226b2
commit
4043f77e36
3
NEWS
3
NEWS
@ -19,6 +19,9 @@ PHP NEWS
|
||||
- Fixed offset/length parameter validation in substr_compare() function. (Ilia)
|
||||
- Fixed debug_zval_dump() to support private and protected members. (Dmitry)
|
||||
- Fixed SoapFault::getMessage(). (Dmitry)
|
||||
- Fixed bug #37017 (strtotime fails before 13:00:00 with some time zones
|
||||
identifiers). (Derick)
|
||||
- Fixed bug #36988 (mktime freezes on long numbers). (Derick)
|
||||
- Fixed bug #36981 (SplFileObject->fgets() ignores max_length). (Tony)
|
||||
- Fixed bug #36957 (serialize() does not handle recursion). (Ilia)
|
||||
- Fixed bug #36944 (strncmp & strncasecmp do not return false on negative
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -97,13 +97,13 @@ typedef unsigned char uchar;
|
||||
|
||||
#define timelib_string_free free
|
||||
|
||||
#define TIMELIB_HAVE_TIME() { if (s->time->have_time) { return TIMELIB_ERROR; } else { s->time->have_time = 1; s->time->h = 0; s->time->i = 0; s->time->s = 0; s->time->f = 0; } }
|
||||
#define TIMELIB_HAVE_TIME() { if (s->time->have_time) { add_error(s, "Double time specification"); timelib_string_free(str); return TIMELIB_ERROR; } else { s->time->have_time = 1; s->time->h = 0; s->time->i = 0; s->time->s = 0; s->time->f = 0; } }
|
||||
#define TIMELIB_UNHAVE_TIME() { s->time->have_time = 0; s->time->h = 0; s->time->i = 0; s->time->s = 0; s->time->f = 0; }
|
||||
#define TIMELIB_HAVE_DATE() { if (s->time->have_date) { return TIMELIB_ERROR; } else { s->time->have_date = 1; } }
|
||||
#define TIMELIB_HAVE_DATE() { if (s->time->have_date) { add_error(s, "Double date specification"); timelib_string_free(str); return TIMELIB_ERROR; } else { s->time->have_date = 1; } }
|
||||
#define TIMELIB_UNHAVE_DATE() { s->time->have_date = 0; s->time->d = 0; s->time->m = 0; s->time->y = 0; }
|
||||
#define TIMELIB_HAVE_RELATIVE() { s->time->have_relative = 1; s->time->relative.weekday_behavior = 0; }
|
||||
#define TIMELIB_HAVE_WEEKDAY_RELATIVE() { s->time->have_weekday_relative = 1; }
|
||||
#define TIMELIB_HAVE_TZ() { s->cur = cursor; if (s->time->have_zone) { return TIMELIB_ERROR; } else { s->time.have_zone = 1; } }
|
||||
#define TIMELIB_HAVE_TZ() { s->cur = cursor; if (s->time->have_zone) { add_warning(s, "Double timezone specification"); timelib_string_free(str); return TIMELIB_ERROR; } else { s->time->have_zone = 1; } }
|
||||
|
||||
#define TIMELIB_INIT s->cur = cursor; str = timelib_string(s); ptr = str
|
||||
#define TIMELIB_DEINIT timelib_string_free(str)
|
||||
@ -140,7 +140,7 @@ typedef struct Scanner {
|
||||
int fd;
|
||||
uchar *lim, *str, *ptr, *cur, *tok, *pos;
|
||||
unsigned int line, len;
|
||||
int errors;
|
||||
struct timelib_error_container *errors;
|
||||
|
||||
struct timelib_time *time;
|
||||
timelib_tzdb *tzdb;
|
||||
@ -325,6 +325,24 @@ uchar *fill(Scanner *s, uchar *cursor){
|
||||
}
|
||||
#endif
|
||||
|
||||
static void add_warning(Scanner *s, char *error)
|
||||
{
|
||||
s->errors->warning_count++;
|
||||
s->errors->warning_messages = realloc(s->errors->warning_messages, s->errors->warning_count * sizeof(timelib_error_message));
|
||||
s->errors->warning_messages[s->errors->warning_count - 1].position = s->tok ? s->tok - s->str : 0;
|
||||
s->errors->warning_messages[s->errors->warning_count - 1].character = s->tok ? *s->tok : 0;
|
||||
s->errors->warning_messages[s->errors->warning_count - 1].message = strdup(error);
|
||||
}
|
||||
|
||||
static void add_error(Scanner *s, char *error)
|
||||
{
|
||||
s->errors->error_count++;
|
||||
s->errors->error_messages = realloc(s->errors->error_messages, s->errors->error_count * sizeof(timelib_error_message));
|
||||
s->errors->error_messages[s->errors->error_count - 1].position = s->tok ? s->tok - s->str : 0;
|
||||
s->errors->error_messages[s->errors->error_count - 1].character = s->tok ? *s->tok : 0;
|
||||
s->errors->error_messages[s->errors->error_count - 1].message = strdup(error);
|
||||
}
|
||||
|
||||
static timelib_sll timelib_meridian(char **ptr, timelib_sll h)
|
||||
{
|
||||
timelib_sll retval = 0;
|
||||
@ -684,9 +702,11 @@ static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_
|
||||
char *tz_abbr;
|
||||
|
||||
t->is_localtime = 1;
|
||||
t->zone_type = TIMELIB_ZONETYPE_ABBR;
|
||||
|
||||
offset = timelib_lookup_zone(ptr, dst, &tz_abbr, &found);
|
||||
if (found) {
|
||||
t->zone_type = TIMELIB_ZONETYPE_ABBR;
|
||||
}
|
||||
#if 0
|
||||
/* If we found a TimeZone identifier, use it */
|
||||
if (tz_name) {
|
||||
@ -702,7 +722,7 @@ static long timelib_get_zone(char **ptr, int *dst, timelib_time *t, int *tz_not_
|
||||
found++;
|
||||
}
|
||||
}
|
||||
if (t->zone_type != TIMELIB_ZONETYPE_ID) {
|
||||
if (found && t->zone_type != TIMELIB_ZONETYPE_ID) {
|
||||
timelib_time_tz_abbr_update(t, tz_abbr);
|
||||
}
|
||||
free(tz_abbr);
|
||||
@ -748,8 +768,8 @@ minute = [0-5]?[0-9];
|
||||
minutelz = [0-5][0-9];
|
||||
second = minute | "60";
|
||||
secondlz = minutelz | "60";
|
||||
meridian = [AaPp] "."? [Mm] "."?;
|
||||
tz = "("? [A-Za-z]{1,4} ")"? | [A-Z][a-z]+([_/][A-Z][a-z]+)+;
|
||||
meridian = ([AaPp] "."? [Mm] "."?) [\000\t ];
|
||||
tz = "("? [A-Za-z]{1,6} ")"? | [A-Z][a-z]+([_/][A-Z][a-z]+)+;
|
||||
tzcorrection = [+-] hour24 ":"? minute?;
|
||||
|
||||
daysuf = "st" | "nd" | "rd" | "th";
|
||||
@ -780,17 +800,17 @@ timetiny12 = hour12 space? meridian;
|
||||
timeshort12 = hour12[:.]minutelz space? meridian;
|
||||
timelong12 = hour12[:.]minute[:.]secondlz space? meridian;
|
||||
|
||||
timeshort24 = hour24[:.]minute;
|
||||
timelong24 = hour24[:.]minute[:.]second;
|
||||
iso8601long = hour24 [:.] minute [:.] second frac;
|
||||
timeshort24 = 't'? hour24[:.]minute;
|
||||
timelong24 = 't'? hour24[:.]minute[:.]second;
|
||||
iso8601long = 't'? hour24 [:.] minute [:.] second frac;
|
||||
|
||||
/* iso8601shorttz = hour24 [:] minutelz space? (tzcorrection | tz); */
|
||||
iso8601normtz = hour24 [:.] minute [:.] secondlz space? (tzcorrection | tz);
|
||||
iso8601normtz = 't'? hour24 [:.] minute [:.] secondlz space? (tzcorrection | tz);
|
||||
/* iso8601longtz = hour24 [:] minute [:] secondlz frac space? (tzcorrection | tz); */
|
||||
|
||||
gnunocolon = hour24lz minutelz;
|
||||
gnunocolon = 't'? hour24lz minutelz;
|
||||
/* gnunocolontz = hour24lz minutelz space? (tzcorrection | tz); */
|
||||
iso8601nocolon = hour24lz minutelz secondlz;
|
||||
iso8601nocolon = 't'? hour24lz minutelz secondlz;
|
||||
/* iso8601nocolontz = hour24lz minutelz secondlz space? (tzcorrection | tz); */
|
||||
|
||||
/* Date formats */
|
||||
@ -960,7 +980,9 @@ relativetext = reltextnumber space? reltextunit;
|
||||
|
||||
if (*ptr != '\0') {
|
||||
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb);
|
||||
s->errors += tz_not_found;
|
||||
if (tz_not_found) {
|
||||
add_error(s, "The timezone could not be found in the database");
|
||||
}
|
||||
}
|
||||
TIMELIB_DEINIT;
|
||||
return TIMELIB_TIME24_WITH_ZONE;
|
||||
@ -981,6 +1003,7 @@ relativetext = reltextnumber space? reltextunit;
|
||||
break;
|
||||
default:
|
||||
TIMELIB_DEINIT;
|
||||
add_error(s, "Double time specification");
|
||||
return TIMELIB_ERROR;
|
||||
}
|
||||
s->time->have_time++;
|
||||
@ -1023,7 +1046,9 @@ relativetext = reltextnumber space? reltextunit;
|
||||
|
||||
if (*ptr != '\0') {
|
||||
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb);
|
||||
s->errors += tz_not_found;
|
||||
if (tz_not_found) {
|
||||
add_error(s, "The timezone could not be found in the database");
|
||||
}
|
||||
}
|
||||
TIMELIB_DEINIT;
|
||||
return TIMELIB_ISO_NOCOLON;
|
||||
@ -1176,7 +1201,9 @@ relativetext = reltextnumber space? reltextunit;
|
||||
s->time->f = timelib_get_frac_nr((char **) &ptr, 9);
|
||||
if (*ptr) { /* timezone is optional */
|
||||
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb);
|
||||
s->errors += tz_not_found;
|
||||
if (tz_not_found) {
|
||||
add_error(s, "The timezone could not be found in the database");
|
||||
}
|
||||
}
|
||||
}
|
||||
TIMELIB_DEINIT;
|
||||
@ -1274,7 +1301,9 @@ relativetext = reltextnumber space? reltextunit;
|
||||
s->time->i = timelib_get_nr((char **) &ptr, 2);
|
||||
s->time->s = timelib_get_nr((char **) &ptr, 2);
|
||||
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb);
|
||||
s->errors += tz_not_found;
|
||||
if (tz_not_found) {
|
||||
add_error(s, "The timezone could not be found in the database");
|
||||
}
|
||||
TIMELIB_DEINIT;
|
||||
return TIMELIB_CLF;
|
||||
}
|
||||
@ -1341,8 +1370,11 @@ relativetext = reltextnumber space? reltextunit;
|
||||
int tz_not_found;
|
||||
DEBUG_OUTPUT("tzcorrection | tz");
|
||||
TIMELIB_INIT;
|
||||
TIMELIB_HAVE_TZ();
|
||||
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb);
|
||||
s->errors += tz_not_found;
|
||||
if (tz_not_found) {
|
||||
add_error(s, "The timezone could not be found in the database");
|
||||
}
|
||||
TIMELIB_DEINIT;
|
||||
return TIMELIB_TIMEZONE;
|
||||
}
|
||||
@ -1369,7 +1401,9 @@ relativetext = reltextnumber space? reltextunit;
|
||||
|
||||
if (*ptr != '\0') {
|
||||
s->time->z = timelib_get_zone((char **) &ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb);
|
||||
s->errors += tz_not_found;
|
||||
if (tz_not_found) {
|
||||
add_error(s, "The timezone could not be found in the database");
|
||||
}
|
||||
}
|
||||
TIMELIB_DEINIT;
|
||||
return TIMELIB_SHORTDATE_WITH_TIME;
|
||||
@ -1404,8 +1438,7 @@ relativetext = reltextnumber space? reltextunit;
|
||||
|
||||
any
|
||||
{
|
||||
/* printf("unexpected character: #%d, %c ", *s->tok, *s->tok); */
|
||||
s->errors++;
|
||||
add_error(s, "Unexpected character");
|
||||
goto std;
|
||||
}
|
||||
*/
|
||||
@ -1413,12 +1446,19 @@ relativetext = reltextnumber space? reltextunit;
|
||||
|
||||
/*!max:re2c */
|
||||
|
||||
timelib_time* timelib_strtotime(char *s, int len, int *errors, timelib_tzdb *tzdb)
|
||||
timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container **errors, timelib_tzdb *tzdb)
|
||||
{
|
||||
Scanner in;
|
||||
int t;
|
||||
char *e = s + len - 1;
|
||||
|
||||
memset(&in, 0, sizeof(in));
|
||||
in.errors = malloc(sizeof(struct timelib_error_container));
|
||||
in.errors->warning_count = 0;
|
||||
in.errors->warning_messages = NULL;
|
||||
in.errors->error_count = 0;
|
||||
in.errors->error_messages = NULL;
|
||||
|
||||
while (isspace(*s) && s < e) {
|
||||
s++;
|
||||
}
|
||||
@ -1426,15 +1466,19 @@ timelib_time* timelib_strtotime(char *s, int len, int *errors, timelib_tzdb *tzd
|
||||
e--;
|
||||
}
|
||||
if (e - s < 1) {
|
||||
*errors = 1;
|
||||
in.time = timelib_time_ctor();
|
||||
add_error(&in, "Empty string");
|
||||
if (errors) {
|
||||
*errors = in.errors;
|
||||
} else {
|
||||
timelib_error_container_dtor(in.errors);
|
||||
}
|
||||
in.time->y = in.time->d = in.time->m = in.time->h = in.time->i = in.time->s = in.time->f = in.time->z = in.time->dst = -1;
|
||||
in.time->is_localtime = in.time->zone_type = 0;
|
||||
return in.time;
|
||||
}
|
||||
e++;
|
||||
|
||||
memset(&in, 0, sizeof(in));
|
||||
in.str = malloc((e - s) + YYMAXFILL);
|
||||
memset(in.str, 0, (e - s) + YYMAXFILL);
|
||||
memcpy(in.str, s, (e - s));
|
||||
@ -1450,7 +1494,6 @@ timelib_time* timelib_strtotime(char *s, int len, int *errors, timelib_tzdb *tzd
|
||||
in.time->f = -1;
|
||||
in.time->z = -1;
|
||||
in.time->dst = -1;
|
||||
in.errors = 0;
|
||||
in.tzdb = tzdb;
|
||||
in.time->is_localtime = 0;
|
||||
in.time->zone_type = 0;
|
||||
@ -1463,7 +1506,11 @@ timelib_time* timelib_strtotime(char *s, int len, int *errors, timelib_tzdb *tzd
|
||||
} while(t != EOI);
|
||||
|
||||
free(in.str);
|
||||
*errors = in.errors;
|
||||
if (errors) {
|
||||
*errors = in.errors;
|
||||
} else {
|
||||
timelib_error_container_dtor(in.errors);
|
||||
}
|
||||
return in.time;
|
||||
}
|
||||
|
||||
|
@ -122,6 +122,21 @@ char *timelib_get_tz_abbr_ptr(timelib_time *t)
|
||||
return t->tz_abbr;
|
||||
}
|
||||
|
||||
void timelib_error_container_dtor(timelib_error_container *errors)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < errors->warning_count; i++) {
|
||||
free(errors->warning_messages[i].message);
|
||||
}
|
||||
free(errors->warning_messages);
|
||||
for (i = 0; i < errors->error_count; i++) {
|
||||
free(errors->error_messages[i].message);
|
||||
}
|
||||
free(errors->error_messages);
|
||||
free(errors);
|
||||
}
|
||||
|
||||
signed long timelib_date_to_int(timelib_time *d, int *error)
|
||||
{
|
||||
timelib_sll ts;
|
||||
|
@ -51,7 +51,7 @@ timelib_sll timelib_days_in_month(timelib_sll y, timelib_sll m);
|
||||
void timelib_isoweek_from_date(timelib_sll y, timelib_sll m, timelib_sll d, timelib_sll *iw, timelib_sll *iy);
|
||||
|
||||
/* From parse_date.re */
|
||||
timelib_time *timelib_strtotime(char *s, int len, int *errors, timelib_tzdb *tzdb);
|
||||
timelib_time *timelib_strtotime(char *s, int len, timelib_error_container **errors, timelib_tzdb *tzdb);
|
||||
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);
|
||||
timelib_tz_lookup_table *timelib_timezone_abbreviations_list(void);
|
||||
@ -90,6 +90,8 @@ void timelib_time_dtor(timelib_time* t);
|
||||
timelib_time_offset* timelib_time_offset_ctor();
|
||||
void timelib_time_offset_dtor(timelib_time_offset* t);
|
||||
|
||||
void timelib_error_container_dtor(timelib_error_container *errors);
|
||||
|
||||
signed long timelib_date_to_int(timelib_time *d, int *error);
|
||||
void timelib_dump_date(timelib_time *d, int options);
|
||||
|
||||
|
@ -147,6 +147,19 @@ typedef struct timelib_time {
|
||||
* 2 TimeZone abbreviation */
|
||||
} timelib_time;
|
||||
|
||||
typedef struct timelib_error_message {
|
||||
int position;
|
||||
char character;
|
||||
char *message;
|
||||
} timelib_error_message;
|
||||
|
||||
typedef struct timelib_error_container {
|
||||
int warning_count;
|
||||
struct timelib_error_message *warning_messages;
|
||||
int error_count;
|
||||
struct timelib_error_message *error_messages;
|
||||
} timelib_error_container;
|
||||
|
||||
typedef struct _timelib_tz_lookup_table {
|
||||
char *name;
|
||||
int type;
|
||||
@ -170,9 +183,10 @@ typedef struct _timelib_tzdb {
|
||||
#define TIMELIB_ZONETYPE_ABBR 2
|
||||
#define TIMELIB_ZONETYPE_ID 3
|
||||
|
||||
#define SECS_PER_DAY 86400
|
||||
#define DAYS_PER_YEAR 365
|
||||
#define DAYS_PER_LYEAR 366
|
||||
#define SECS_PER_ERA 12622780800L
|
||||
#define SECS_PER_DAY 86400
|
||||
#define DAYS_PER_YEAR 365
|
||||
#define DAYS_PER_LYEAR 366
|
||||
|
||||
#define timelib_is_leap(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
|
||||
|
||||
|
@ -135,6 +135,13 @@ static timelib_sll do_years(timelib_sll year)
|
||||
{
|
||||
timelib_sll i;
|
||||
timelib_sll res = 0;
|
||||
timelib_sll eras;
|
||||
|
||||
eras = (year - 1970) / 400;
|
||||
if (eras != 0) {
|
||||
year = year - (eras * 400);
|
||||
res += (SECS_PER_ERA * eras);
|
||||
}
|
||||
|
||||
if (year >= 1970) {
|
||||
for (i = year - 1; i >= 1970; i--) {
|
||||
|
@ -51,6 +51,7 @@ zend_function_entry date_functions[] = {
|
||||
#ifdef EXPERIMENTAL_DATE_SUPPORT
|
||||
/* Advanced Interface */
|
||||
PHP_FE(date_create, NULL)
|
||||
PHP_FE(date_parse, NULL)
|
||||
PHP_FE(date_format, NULL)
|
||||
PHP_FE(date_modify, NULL)
|
||||
PHP_FE(date_timezone_get, NULL)
|
||||
@ -63,6 +64,7 @@ zend_function_entry date_functions[] = {
|
||||
|
||||
PHP_FE(timezone_open, NULL)
|
||||
PHP_FE(timezone_name_get, NULL)
|
||||
PHP_FE(timezone_name_from_abbr, NULL)
|
||||
PHP_FE(timezone_offset_get, NULL)
|
||||
PHP_FE(timezone_transistions_get, NULL)
|
||||
PHP_FE(timezone_identifiers_list, NULL)
|
||||
@ -269,6 +271,7 @@ PHP_MINIT_FUNCTION(date)
|
||||
REGISTER_STRING_CONSTANT("DATE_RFC1036", DATE_FORMAT_RFC1036, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_STRING_CONSTANT("DATE_RFC1123", DATE_FORMAT_RFC1123, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_STRING_CONSTANT("DATE_RFC2822", DATE_FORMAT_RFC2822, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_STRING_CONSTANT("DATE_RFC3339", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_STRING_CONSTANT("DATE_RSS", DATE_FORMAT_RFC1123, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_STRING_CONSTANT("DATE_W3C", DATE_FORMAT_RFC3339, CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
@ -793,14 +796,14 @@ PHPAPI void php_date_set_tzdb(timelib_tzdb *tzdb)
|
||||
PHPAPI signed long php_parse_date(char *string, signed long *now)
|
||||
{
|
||||
timelib_time *parsed_time;
|
||||
int error1, error2;
|
||||
int error2;
|
||||
signed long retval;
|
||||
|
||||
parsed_time = timelib_strtotime(string, strlen(string), &error1, DATE_TIMEZONEDB);
|
||||
parsed_time = timelib_strtotime(string, strlen(string), NULL, DATE_TIMEZONEDB);
|
||||
timelib_update_ts(parsed_time, NULL);
|
||||
retval = timelib_date_to_int(parsed_time, &error2);
|
||||
timelib_time_dtor(parsed_time);
|
||||
if (error1 || error2) {
|
||||
if (error2) {
|
||||
return -1;
|
||||
}
|
||||
return retval;
|
||||
@ -808,12 +811,13 @@ PHPAPI signed long php_parse_date(char *string, signed long *now)
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto int strtotime(string time, int now)
|
||||
/* {{{ proto int strtotime(string time [, int now ])
|
||||
Convert string representation of date and time to a timestamp */
|
||||
PHP_FUNCTION(strtotime)
|
||||
{
|
||||
char *times, *initial_ts;
|
||||
int time_len, error1, error2;
|
||||
struct timelib_error_container *error;
|
||||
long preset_ts, ts;
|
||||
|
||||
timelib_time *t, *now;
|
||||
@ -827,7 +831,7 @@ PHP_FUNCTION(strtotime)
|
||||
|
||||
initial_ts = emalloc(25);
|
||||
snprintf(initial_ts, 24, "@%ld", preset_ts);
|
||||
t = timelib_strtotime(initial_ts, strlen(initial_ts), &error1, DATE_TIMEZONEDB); /* we ignore the error here, as this should never fail */
|
||||
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;
|
||||
now->zone_type = TIMELIB_ZONETYPE_ID;
|
||||
@ -844,7 +848,9 @@ PHP_FUNCTION(strtotime)
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
t = timelib_strtotime(times, time_len, &error1, DATE_TIMEZONEDB);
|
||||
t = timelib_strtotime(times, time_len, &error, DATE_TIMEZONEDB);
|
||||
error1 = error->error_count;
|
||||
timelib_error_container_dtor(error);
|
||||
timelib_fill_holes(t, now, 0);
|
||||
timelib_update_ts(t, tzi);
|
||||
ts = timelib_date_to_int(t, &error2);
|
||||
@ -1299,7 +1305,6 @@ PHP_FUNCTION(date_create)
|
||||
{
|
||||
php_date_obj *dateobj;
|
||||
zval *timezone_object = NULL;
|
||||
int error;
|
||||
timelib_time *now;
|
||||
timelib_tzinfo *tzi;
|
||||
char *time_str;
|
||||
@ -1311,7 +1316,7 @@ PHP_FUNCTION(date_create)
|
||||
|
||||
date_instanciate(date_ce_date, return_value TSRMLS_CC);
|
||||
dateobj = (php_date_obj *) zend_object_store_get_object(return_value TSRMLS_CC);
|
||||
dateobj->time = timelib_strtotime(time_str_len ? time_str : "now", time_str_len ? time_str_len : sizeof("now") -1, &error, DATE_TIMEZONEDB);
|
||||
dateobj->time = timelib_strtotime(time_str_len ? time_str : "now", time_str_len ? time_str_len : sizeof("now") -1, NULL, DATE_TIMEZONEDB);
|
||||
|
||||
if (timezone_object) {
|
||||
php_timezone_obj *tzobj;
|
||||
@ -1343,6 +1348,101 @@ PHP_FUNCTION(date_create)
|
||||
timelib_time_dtor(now);
|
||||
}
|
||||
|
||||
PHP_FUNCTION(date_parse)
|
||||
{
|
||||
char *date;
|
||||
int date_len, i;
|
||||
struct timelib_error_container *error;
|
||||
timelib_time *parsed_time;
|
||||
zval *element;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &date, &date_len) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
parsed_time = timelib_strtotime(date, date_len, &error, DATE_TIMEZONEDB);
|
||||
array_init(return_value);
|
||||
#define PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(name, elem) \
|
||||
if (parsed_time->elem == -1) { \
|
||||
add_assoc_bool(return_value, #name, 0); \
|
||||
} else { \
|
||||
add_assoc_long(return_value, #name, parsed_time->elem); \
|
||||
}
|
||||
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(year, y);
|
||||
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(month, m);
|
||||
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(day, d);
|
||||
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 == -1) {
|
||||
add_assoc_bool(return_value, "fraction", 0);
|
||||
} else {
|
||||
add_assoc_double(return_value, "fraction", parsed_time->f);
|
||||
}
|
||||
|
||||
add_assoc_long(return_value, "warning_count", error->warning_count);
|
||||
MAKE_STD_ZVAL(element);
|
||||
array_init(element);
|
||||
for (i = 0; i < error->warning_count; i++) {
|
||||
add_index_string(element, error->warning_messages[i].position, error->warning_messages[i].message, 1);
|
||||
}
|
||||
add_assoc_zval(return_value, "warnings", element);
|
||||
|
||||
add_assoc_long(return_value, "error_count", error->error_count);
|
||||
MAKE_STD_ZVAL(element);
|
||||
array_init(element);
|
||||
for (i = 0; i < error->error_count; i++) {
|
||||
add_index_string(element, error->error_messages[i].position, error->error_messages[i].message, 1);
|
||||
}
|
||||
add_assoc_zval(return_value, "errors", element);
|
||||
timelib_error_container_dtor(error);
|
||||
|
||||
add_assoc_bool(return_value, "is_localtime", parsed_time->is_localtime);
|
||||
|
||||
if (parsed_time->is_localtime) {
|
||||
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(zone_type, zone_type);
|
||||
switch (parsed_time->zone_type) {
|
||||
case TIMELIB_ZONETYPE_OFFSET:
|
||||
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(zone, z);
|
||||
add_assoc_bool(return_value, "is_dst", parsed_time->dst);
|
||||
break;
|
||||
case TIMELIB_ZONETYPE_ID:
|
||||
if (parsed_time->tz_abbr) {
|
||||
add_assoc_string(return_value, "tz_abbr", parsed_time->tz_abbr, 1);
|
||||
}
|
||||
if (parsed_time->tz_info) {
|
||||
add_assoc_string(return_value, "tz_id", parsed_time->tz_info->name, 1);
|
||||
}
|
||||
break;
|
||||
case TIMELIB_ZONETYPE_ABBR:
|
||||
PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(zone, z);
|
||||
add_assoc_bool(return_value, "is_dst", parsed_time->dst);
|
||||
add_assoc_string(return_value, "tz_abbr", parsed_time->tz_abbr, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parsed_time->have_relative || parsed_time->have_weekday_relative) {
|
||||
MAKE_STD_ZVAL(element);
|
||||
array_init(element);
|
||||
}
|
||||
if (parsed_time->have_relative) {
|
||||
add_assoc_long(element, "year", parsed_time->relative.y);
|
||||
add_assoc_long(element, "month", parsed_time->relative.m);
|
||||
add_assoc_long(element, "day", parsed_time->relative.d);
|
||||
add_assoc_long(element, "hour", parsed_time->relative.h);
|
||||
add_assoc_long(element, "minute", parsed_time->relative.i);
|
||||
add_assoc_long(element, "second", parsed_time->relative.s);
|
||||
}
|
||||
if (parsed_time->have_weekday_relative) {
|
||||
add_assoc_long(element, "weekday", parsed_time->relative.weekday);
|
||||
}
|
||||
if (parsed_time->have_relative || parsed_time->have_weekday_relative) {
|
||||
add_assoc_zval(return_value, "relative", element);
|
||||
}
|
||||
timelib_time_dtor(parsed_time);
|
||||
}
|
||||
|
||||
PHP_FUNCTION(date_format)
|
||||
{
|
||||
zval *object;
|
||||
@ -1363,7 +1463,6 @@ PHP_FUNCTION(date_modify)
|
||||
php_date_obj *dateobj;
|
||||
char *modify;
|
||||
int modify_len;
|
||||
int error;
|
||||
timelib_time *tmp_time;
|
||||
|
||||
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &object, date_ce_date, &modify, &modify_len) == FAILURE) {
|
||||
@ -1371,7 +1470,7 @@ PHP_FUNCTION(date_modify)
|
||||
}
|
||||
dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
tmp_time = timelib_strtotime(modify, modify_len, &error, DATE_TIMEZONEDB);
|
||||
tmp_time = timelib_strtotime(modify, modify_len, NULL, DATE_TIMEZONEDB);
|
||||
dateobj->time->relative.y = tmp_time->relative.y;
|
||||
dateobj->time->relative.m = tmp_time->relative.m;
|
||||
dateobj->time->relative.d = tmp_time->relative.d;
|
||||
@ -1544,6 +1643,26 @@ PHP_FUNCTION(timezone_name_get)
|
||||
RETURN_STRING(tzobj->tz->name, 1);
|
||||
}
|
||||
|
||||
PHP_FUNCTION(timezone_name_from_abbr)
|
||||
{
|
||||
char *abbr;
|
||||
char *tzname;
|
||||
int abbr_len;
|
||||
long gmtoffset = -1;
|
||||
long isdst = -1;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &abbr, &abbr_len, &gmtoffset, &isdst) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
tzname = timelib_timezone_id_from_abbr(abbr, gmtoffset, isdst);
|
||||
|
||||
if (tzname) {
|
||||
RETURN_STRING(tzname, 1);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
PHP_FUNCTION(timezone_offset_get)
|
||||
{
|
||||
zval *object, *dateobject;
|
||||
|
@ -49,6 +49,7 @@ PHP_FUNCTION(getdate);
|
||||
#ifdef EXPERIMENTAL_DATE_SUPPORT
|
||||
/* Advanced Interface */
|
||||
PHP_FUNCTION(date_create);
|
||||
PHP_FUNCTION(date_parse);
|
||||
PHP_FUNCTION(date_format);
|
||||
PHP_FUNCTION(date_modify);
|
||||
PHP_FUNCTION(date_timezone_get);
|
||||
@ -61,6 +62,7 @@ PHP_FUNCTION(date_isodate_set);
|
||||
|
||||
PHP_FUNCTION(timezone_open);
|
||||
PHP_FUNCTION(timezone_name_get);
|
||||
PHP_FUNCTION(timezone_name_from_abbr);
|
||||
PHP_FUNCTION(timezone_offset_get);
|
||||
PHP_FUNCTION(timezone_transistions_get);
|
||||
PHP_FUNCTION(timezone_identifiers_list);
|
||||
|
10
ext/date/tests/bug36988.phpt
Normal file
10
ext/date/tests/bug36988.phpt
Normal file
@ -0,0 +1,10 @@
|
||||
--TEST--
|
||||
Bug #36988 (mktime freezes on long numbers)
|
||||
--FILE--
|
||||
<?php
|
||||
$start = microtime(true);
|
||||
$a = mktime(1, 1, 1, 1, 1, 11111111111);
|
||||
echo (microtime(true) - $start) < 1 ? "smaller than one second" : "more than a second";
|
||||
?>
|
||||
--EXPECT--
|
||||
smaller than one second
|
14
ext/date/tests/bug37017.phpt
Normal file
14
ext/date/tests/bug37017.phpt
Normal file
@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
Bug #37017 (strtotime fails before 13:00:00 with some time zones identifiers).
|
||||
--FILE--
|
||||
<?php
|
||||
echo strtotime("2006-05-12 13:00:01 America/New_York"), "\n";
|
||||
echo strtotime("2006-05-12 13:00:00 America/New_York"), "\n";
|
||||
echo strtotime("2006-05-12 12:59:59 America/New_York"), "\n";
|
||||
echo strtotime("2006-05-12 12:59:59 GMT"), "\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
1147453201
|
||||
1147453200
|
||||
1147453199
|
||||
1147438799
|
Loading…
Reference in New Issue
Block a user