From 06d4c70e5179baab2311c4b6e77760a101715de6 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Wed, 14 Sep 2022 16:33:05 +0100 Subject: [PATCH 1/4] Integrate timelib 2022.02 - Fixed #124: Can't parse INT_MIN - Added a new API, timelib_get_time_zone_offset_info, which reduces allocation speeding up algorithms (Alberto Massari) - Accelerate the do_range_limit_days algorythm by advancing multiple months in a single call (Alberto Massari) Including fixes from 2021.17: - Fixed 'const' and other compiler warnings - Use new 'PACKRAT' format to prevent old timestamps from becoming incorrect - New 2022b data file - Fixed PHP GH-9165: strtotime translates a date-time with DST/non-DST hour differently --- ext/date/lib/README.rst | 2 +- ext/date/lib/interval.c | 50 +++--- ext/date/lib/parse_date.c | 267 +++++++++++++++------------- ext/date/lib/parse_date.re | 63 +++++-- ext/date/lib/parse_iso_intervals.c | 4 +- ext/date/lib/parse_iso_intervals.re | 2 +- ext/date/lib/parse_tz.c | 37 +++- ext/date/lib/timelib.h | 27 ++- ext/date/lib/timelib_private.h | 14 ++ ext/date/lib/tm2unixtime.c | 95 +++++----- ext/date/lib/unixtime2tm.c | 7 +- 11 files changed, 337 insertions(+), 231 deletions(-) diff --git a/ext/date/lib/README.rst b/ext/date/lib/README.rst index 7a6d856c6ed..80b959b579a 100644 --- a/ext/date/lib/README.rst +++ b/ext/date/lib/README.rst @@ -11,4 +11,4 @@ support. Build Requirements ------------------ -On Debian: ``apt install libcpputest-dev`` +On Debian: ``apt install libcpputest-dev re2c`` diff --git a/ext/date/lib/interval.c b/ext/date/lib/interval.c index d7a05d16ea9..ee4451b6aca 100644 --- a/ext/date/lib/interval.c +++ b/ext/date/lib/interval.c @@ -90,8 +90,9 @@ static void sort_old_to_new(timelib_time **one, timelib_time **two, timelib_rel_ static timelib_rel_time *timelib_diff_with_tzid(timelib_time *one, timelib_time *two) { timelib_rel_time *rt; - timelib_sll dst_corr = 0, dst_h_corr = 0, dst_m_corr = 0; - timelib_time_offset *trans = NULL; + timelib_sll dst_corr = 0, dst_h_corr = 0, dst_m_corr = 0; + int32_t trans_offset; + timelib_sll trans_transition_time; rt = timelib_rel_time_ctor(); rt->invert = 0; @@ -117,16 +118,16 @@ static timelib_rel_time *timelib_diff_with_tzid(timelib_time *one, timelib_time if (one->dst == 1 && two->dst == 0) { /* First for two "Type 3" times */ if (one->zone_type == TIMELIB_ZONETYPE_ID && two->zone_type == TIMELIB_ZONETYPE_ID) { - trans = timelib_get_time_zone_info(two->sse, two->tz_info); - if (trans) { - if (one->sse < trans->transition_time && one->sse >= trans->transition_time + dst_corr) { + int success = timelib_get_time_zone_offset_info(two->sse, two->tz_info, &trans_offset, &trans_transition_time, NULL); + if ( + success && + one->sse < trans_transition_time && + one->sse >= trans_transition_time + dst_corr + ) { timelib_sll flipped = SECS_PER_HOUR + (rt->i * 60) + (rt->s); rt->h = flipped / SECS_PER_HOUR; rt->i = (flipped - rt->h * SECS_PER_HOUR) / 60; rt->s = flipped % 60; - } - timelib_time_offset_dtor(trans); - trans = NULL; } } else if (rt->h == 0 && (rt->i < 0 || rt->s < 0)) { /* Then for all the others */ @@ -145,12 +146,12 @@ static timelib_rel_time *timelib_diff_with_tzid(timelib_time *one, timelib_time if (one->zone_type == TIMELIB_ZONETYPE_ID && two->zone_type == TIMELIB_ZONETYPE_ID && strcmp(one->tz_info->name, two->tz_info->name) == 0) { if (one->dst == 1 && two->dst == 0) { /* Fall Back */ if (two->tz_info) { - trans = timelib_get_time_zone_info(two->sse, two->tz_info); + int success = timelib_get_time_zone_offset_info(two->sse, two->tz_info, &trans_offset, &trans_transition_time, NULL); if ( - trans && - two->sse >= trans->transition_time && - ((two->sse - one->sse + dst_corr) % SECS_PER_DAY) > (two->sse - trans->transition_time) + success && + two->sse >= trans_transition_time && + ((two->sse - one->sse + dst_corr) % SECS_PER_DAY) > (two->sse - trans_transition_time) ) { rt->h -= dst_h_corr; rt->i -= dst_m_corr; @@ -158,13 +159,13 @@ static timelib_rel_time *timelib_diff_with_tzid(timelib_time *one, timelib_time } } else if (one->dst == 0 && two->dst == 1) { /* Spring Forward */ if (two->tz_info) { - trans = timelib_get_time_zone_info(two->sse, two->tz_info); + int success = timelib_get_time_zone_offset_info(two->sse, two->tz_info, &trans_offset, &trans_transition_time, NULL); if ( - trans && - !((one->sse + SECS_PER_DAY > trans->transition_time) && (one->sse + SECS_PER_DAY <= (trans->transition_time + dst_corr))) && - two->sse >= trans->transition_time && - ((two->sse - one->sse + dst_corr) % SECS_PER_DAY) > (two->sse - trans->transition_time) + success && + !((one->sse + SECS_PER_DAY > trans_transition_time) && (one->sse + SECS_PER_DAY <= (trans_transition_time + dst_corr))) && + two->sse >= trans_transition_time && + ((two->sse - one->sse + dst_corr) % SECS_PER_DAY) > (two->sse - trans_transition_time) ) { rt->h -= dst_h_corr; rt->i -= dst_m_corr; @@ -172,12 +173,13 @@ static timelib_rel_time *timelib_diff_with_tzid(timelib_time *one, timelib_time } } else if (two->sse - one->sse >= SECS_PER_DAY) { /* Check whether we're in the period to the next transition time */ - trans = timelib_get_time_zone_info(two->sse - two->z, two->tz_info); - dst_corr = one->z - trans->offset; + if (timelib_get_time_zone_offset_info(two->sse - two->z, two->tz_info, &trans_offset, &trans_transition_time, NULL)) { + dst_corr = one->z - trans_offset; - if (two->sse >= trans->transition_time - dst_corr && two->sse < trans->transition_time) { - rt->d--; - rt->h = 24; + if (two->sse >= trans_transition_time - dst_corr && two->sse < trans_transition_time) { + rt->d--; + rt->h = 24; + } } } } else { @@ -189,10 +191,6 @@ static timelib_rel_time *timelib_diff_with_tzid(timelib_time *one, timelib_time timelib_do_rel_normalize(rt->invert ? one : two, rt); } - if (trans) { - timelib_time_offset_dtor(trans); - } - return rt; } diff --git a/ext/date/lib/parse_date.c b/ext/date/lib/parse_date.c index 62fdc0d90dd..06d0039b700 100644 --- a/ext/date/lib/parse_date.c +++ b/ext/date/lib/parse_date.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.15.3 on Fri Jul 22 15:29:55 2022 */ +/* Generated by re2c 0.15.3 on Wed Sep 14 16:31:52 2022 */ #line 1 "ext/date/lib/parse_date.re" /* * The MIT License (MIT) @@ -362,7 +362,7 @@ static timelib_error_message *alloc_error_message(timelib_error_message **messag return *messages + (*count)++; } -static void add_warning(Scanner *s, int error_code, char *error) +static void add_warning(Scanner *s, int error_code, const char *error) { timelib_error_message *message = alloc_error_message(&s->errors->warning_messages, &s->errors->warning_count); @@ -372,7 +372,7 @@ static void add_warning(Scanner *s, int error_code, char *error) message->message = timelib_strdup(error); } -static void add_error(Scanner *s, int error_code, char *error) +static void add_error(Scanner *s, int error_code, const char *error) { timelib_error_message *message = alloc_error_message(&s->errors->error_messages, &s->errors->error_count); @@ -382,7 +382,7 @@ static void add_error(Scanner *s, int error_code, char *error) message->message = timelib_strdup(error); } -static void add_pbf_warning(Scanner *s, int error_code, char *error, const char *sptr, const char *cptr) +static void add_pbf_warning(Scanner *s, int error_code, const char *error, const char *sptr, const char *cptr) { timelib_error_message *message = alloc_error_message(&s->errors->warning_messages, &s->errors->warning_count); @@ -392,7 +392,7 @@ static void add_pbf_warning(Scanner *s, int error_code, char *error, const char message->message = timelib_strdup(error); } -static void add_pbf_error(Scanner *s, int error_code, char *error, const char *sptr, const char *cptr) +static void add_pbf_error(Scanner *s, int error_code, const char *error, const char *sptr, const char *cptr) { timelib_error_message *message = alloc_error_message(&s->errors->error_messages, &s->errors->error_count); @@ -486,6 +486,7 @@ static timelib_sll timelib_get_nr_ex(const char **ptr, int max_length, int *scan } ++*ptr; } + begin = *ptr; while ((**ptr >= '0') && (**ptr <= '9') && len < max_length) { ++*ptr; @@ -543,24 +544,49 @@ static timelib_sll timelib_get_frac_nr(const char **ptr) static timelib_ull timelib_get_signed_nr(Scanner *s, const char **ptr, int max_length) { - timelib_ull dir = 1; + char *str, *str_ptr; + timelib_sll tmp_nr = 0; + int len = 0; + + str = timelib_calloc(1, max_length + 2); // for sign and \0 + str_ptr = str; while (((**ptr < '0') || (**ptr > '9')) && (**ptr != '+') && (**ptr != '-')) { if (**ptr == '\0') { + add_error(s, TIMELIB_ERR_UNEXPECTED_DATA, "Found unexpected data"); + timelib_free(str); + return 0; + } + ++*ptr; + } + + if ((**ptr == '+') || (**ptr == '-')) { + *str_ptr = **ptr; + ++*ptr; + ++str_ptr; + } + + while (((**ptr < '0') || (**ptr > '9'))) { + if (**ptr == '\0') { + timelib_free(str); add_error(s, TIMELIB_ERR_UNEXPECTED_DATA, "Found unexpected data"); return 0; } ++*ptr; } - while (**ptr == '+' || **ptr == '-') - { - if (**ptr == '-') { - dir *= -1; - } + while ((**ptr >= '0') && (**ptr <= '9') && len < max_length) { + *str_ptr = **ptr; ++*ptr; + ++str_ptr; + ++len; } - return dir * timelib_get_nr(ptr, max_length); + + tmp_nr = strtoll(str, NULL, 10); + + timelib_free(str); + + return tmp_nr; } static timelib_sll timelib_lookup_relative_text(const char **ptr, int *behavior) @@ -952,11 +978,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper) std: s->tok = cursor; s->len = 0; -#line 1085 "ext/date/lib/parse_date.re" +#line 1109 "ext/date/lib/parse_date.re" -#line 962 "" +#line 986 "" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -1094,7 +1120,7 @@ yy2: } yy3: YYDEBUG(3, *YYCURSOR); -#line 1819 "ext/date/lib/parse_date.re" +#line 1843 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("tzcorrection | tz"); @@ -1107,7 +1133,7 @@ yy3: TIMELIB_DEINIT; return TIMELIB_TIMEZONE; } -#line 1113 "" +#line 1137 "" yy4: YYDEBUG(4, *YYCURSOR); yych = *++YYCURSOR; @@ -1414,12 +1440,12 @@ yy11: if (yych <= '9') goto yy1483; yy12: YYDEBUG(12, *YYCURSOR); -#line 1914 "ext/date/lib/parse_date.re" +#line 1938 "ext/date/lib/parse_date.re" { add_error(s, TIMELIB_ERR_UNEXPECTED_CHARACTER, "Unexpected character"); goto std; } -#line 1425 "" +#line 1449 "" yy13: YYDEBUG(13, *YYCURSOR); yych = *++YYCURSOR; @@ -2663,11 +2689,11 @@ yy48: if (yych <= '9') goto yy54; yy49: YYDEBUG(49, *YYCURSOR); -#line 1903 "ext/date/lib/parse_date.re" +#line 1927 "ext/date/lib/parse_date.re" { goto std; } -#line 2673 "" +#line 2697 "" yy50: YYDEBUG(50, *YYCURSOR); yych = *++YYCURSOR; @@ -2676,12 +2702,12 @@ yy51: YYDEBUG(51, *YYCURSOR); ++YYCURSOR; YYDEBUG(52, *YYCURSOR); -#line 1908 "ext/date/lib/parse_date.re" +#line 1932 "ext/date/lib/parse_date.re" { s->pos = cursor; s->line++; goto std; } -#line 2687 "" +#line 2711 "" yy53: YYDEBUG(53, *YYCURSOR); yych = *++YYCURSOR; @@ -3103,7 +3129,7 @@ yy83: if (yych == 's') goto yy85; yy84: YYDEBUG(84, *YYCURSOR); -#line 1887 "ext/date/lib/parse_date.re" +#line 1911 "ext/date/lib/parse_date.re" { timelib_ull i; DEBUG_OUTPUT("relative"); @@ -3118,7 +3144,7 @@ yy84: TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 3124 "" +#line 3148 "" yy85: YYDEBUG(85, *YYCURSOR); yych = *++YYCURSOR; @@ -4127,7 +4153,7 @@ yy218: } yy219: YYDEBUG(219, *YYCURSOR); -#line 1750 "ext/date/lib/parse_date.re" +#line 1774 "ext/date/lib/parse_date.re" { const timelib_relunit* relunit; DEBUG_OUTPUT("daytext"); @@ -4144,7 +4170,7 @@ yy219: TIMELIB_DEINIT; return TIMELIB_WEEKDAY; } -#line 4150 "" +#line 4174 "" yy220: YYDEBUG(220, *YYCURSOR); yych = *++YYCURSOR; @@ -4690,7 +4716,7 @@ yy247: } yy248: YYDEBUG(248, *YYCURSOR); -#line 1809 "ext/date/lib/parse_date.re" +#line 1833 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("monthtext"); TIMELIB_INIT; @@ -4699,7 +4725,7 @@ yy248: TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 4705 "" +#line 4729 "" yy249: YYDEBUG(249, *YYCURSOR); ++YYCURSOR; @@ -4948,7 +4974,7 @@ yy261: goto yy267; yy262: YYDEBUG(262, *YYCURSOR); -#line 1555 "ext/date/lib/parse_date.re" +#line 1579 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datetextual | datenoyear"); @@ -4961,7 +4987,7 @@ yy262: TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 4967 "" +#line 4991 "" yy263: YYDEBUG(263, *YYCURSOR); yyaccept = 6; @@ -5088,7 +5114,7 @@ yy275: } yy276: YYDEBUG(276, *YYCURSOR); -#line 1857 "ext/date/lib/parse_date.re" +#line 1881 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz"); @@ -5117,7 +5143,7 @@ yy276: TIMELIB_DEINIT; return TIMELIB_SHORTDATE_WITH_TIME; } -#line 5123 "" +#line 5147 "" yy277: YYDEBUG(277, *YYCURSOR); yyaccept = 7; @@ -5415,7 +5441,7 @@ yy300: YYDEBUG(300, *YYCURSOR); ++YYCURSOR; YYDEBUG(301, *YYCURSOR); -#line 1833 "ext/date/lib/parse_date.re" +#line 1857 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12"); TIMELIB_INIT; @@ -5438,7 +5464,7 @@ yy300: TIMELIB_DEINIT; return TIMELIB_SHORTDATE_WITH_TIME; } -#line 5444 "" +#line 5468 "" yy302: YYDEBUG(302, *YYCURSOR); yych = *++YYCURSOR; @@ -6116,7 +6142,7 @@ yy361: YYDEBUG(362, *YYCURSOR); ++YYCURSOR; YYDEBUG(363, *YYCURSOR); -#line 1527 "ext/date/lib/parse_date.re" +#line 1551 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datenoday"); @@ -6129,7 +6155,7 @@ yy361: TIMELIB_DEINIT; return TIMELIB_DATE_NO_DAY; } -#line 6135 "" +#line 6159 "" yy364: YYDEBUG(364, *YYCURSOR); yych = *++YYCURSOR; @@ -6360,7 +6386,7 @@ yy368: if (yych <= '9') goto yy372; yy371: YYDEBUG(371, *YYCURSOR); -#line 1671 "ext/date/lib/parse_date.re" +#line 1695 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgtextshort"); @@ -6373,7 +6399,7 @@ yy371: TIMELIB_DEINIT; return TIMELIB_PG_TEXT; } -#line 6379 "" +#line 6403 "" yy372: YYDEBUG(372, *YYCURSOR); yych = *++YYCURSOR; @@ -6955,7 +6981,7 @@ yy397: } yy398: YYDEBUG(398, *YYCURSOR); -#line 1729 "ext/date/lib/parse_date.re" +#line 1753 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("ago"); TIMELIB_INIT; @@ -6975,7 +7001,7 @@ yy398: TIMELIB_DEINIT; return TIMELIB_AGO; } -#line 6981 "" +#line 7005 "" yy399: YYDEBUG(399, *YYCURSOR); yyaccept = 5; @@ -8764,7 +8790,7 @@ yy460: ++YYCURSOR; yy461: YYDEBUG(461, *YYCURSOR); -#line 1420 "ext/date/lib/parse_date.re" +#line 1444 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash"); TIMELIB_INIT; @@ -8775,7 +8801,7 @@ yy461: TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 8781 "" +#line 8805 "" yy462: YYDEBUG(462, *YYCURSOR); yych = *++YYCURSOR; @@ -8897,7 +8923,7 @@ yy484: YYDEBUG(484, *YYCURSOR); ++YYCURSOR; YYDEBUG(485, *YYCURSOR); -#line 1446 "ext/date/lib/parse_date.re" +#line 1470 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("iso8601datex"); TIMELIB_INIT; @@ -8908,7 +8934,7 @@ yy484: TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 8914 "" +#line 8938 "" yy486: YYDEBUG(486, *YYCURSOR); yyaccept = 1; @@ -9662,7 +9688,7 @@ yy508: } yy509: YYDEBUG(509, *YYCURSOR); -#line 1569 "ext/date/lib/parse_date.re" +#line 1593 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("datenoyearrev"); TIMELIB_INIT; @@ -9673,7 +9699,7 @@ yy509: TIMELIB_DEINIT; return TIMELIB_DATE_TEXT; } -#line 9679 "" +#line 9703 "" yy510: YYDEBUG(510, *YYCURSOR); yyaccept = 9; @@ -9814,7 +9840,7 @@ yy521: YYDEBUG(521, *YYCURSOR); ++YYCURSOR; YYDEBUG(522, *YYCURSOR); -#line 1273 "ext/date/lib/parse_date.re" +#line 1297 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12"); TIMELIB_INIT; @@ -9830,7 +9856,7 @@ yy521: TIMELIB_DEINIT; return TIMELIB_TIME12; } -#line 9836 "" +#line 9860 "" yy523: YYDEBUG(523, *YYCURSOR); yyaccept = 10; @@ -9843,7 +9869,7 @@ yy523: } yy524: YYDEBUG(524, *YYCURSOR); -#line 1310 "ext/date/lib/parse_date.re" +#line 1334 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("timetiny24 | timeshort24 | timelong24 | iso8601long"); @@ -9870,7 +9896,7 @@ yy524: TIMELIB_DEINIT; return TIMELIB_TIME24_WITH_ZONE; } -#line 9876 "" +#line 9900 "" yy525: YYDEBUG(525, *YYCURSOR); yyaccept = 10; @@ -10183,7 +10209,7 @@ yy556: YYDEBUG(556, *YYCURSOR); ++YYCURSOR; YYDEBUG(557, *YYCURSOR); -#line 1290 "ext/date/lib/parse_date.re" +#line 1314 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("mssqltime"); TIMELIB_INIT; @@ -10202,7 +10228,7 @@ yy556: TIMELIB_DEINIT; return TIMELIB_TIME24_WITH_ZONE; } -#line 10208 "" +#line 10232 "" yy558: YYDEBUG(558, *YYCURSOR); yyaccept = 10; @@ -10308,7 +10334,7 @@ yy567: if (yych <= '9') goto yy574; yy568: YYDEBUG(568, *YYCURSOR); -#line 1486 "ext/date/lib/parse_date.re" +#line 1510 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datefull"); @@ -10322,7 +10348,7 @@ yy568: TIMELIB_DEINIT; return TIMELIB_DATE_FULL; } -#line 10328 "" +#line 10352 "" yy569: YYDEBUG(569, *YYCURSOR); yych = *++YYCURSOR; @@ -11058,7 +11084,7 @@ yy638: YYDEBUG(639, *YYCURSOR); ++YYCURSOR; YYDEBUG(640, *YYCURSOR); -#line 1501 "ext/date/lib/parse_date.re" +#line 1525 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("pointed date YYYY"); TIMELIB_INIT; @@ -11069,7 +11095,7 @@ yy638: TIMELIB_DEINIT; return TIMELIB_DATE_FULL_POINTED; } -#line 11075 "" +#line 11099 "" yy641: YYDEBUG(641, *YYCURSOR); yyaccept = 10; @@ -11105,7 +11131,7 @@ yy644: if (yych <= '9') goto yy638; yy645: YYDEBUG(645, *YYCURSOR); -#line 1513 "ext/date/lib/parse_date.re" +#line 1537 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pointed date YY"); @@ -11118,7 +11144,7 @@ yy645: TIMELIB_DEINIT; return TIMELIB_DATE_FULL_POINTED; } -#line 11124 "" +#line 11148 "" yy646: YYDEBUG(646, *YYCURSOR); yyaccept = 10; @@ -11759,7 +11785,7 @@ yy689: } yy690: YYDEBUG(690, *YYCURSOR); -#line 1472 "ext/date/lib/parse_date.re" +#line 1496 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("gnudateshort"); @@ -11772,7 +11798,7 @@ yy690: TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 11778 "" +#line 11802 "" yy691: YYDEBUG(691, *YYCURSOR); yyaccept = 12; @@ -11878,7 +11904,7 @@ yy699: } yy700: YYDEBUG(700, *YYCURSOR); -#line 1404 "ext/date/lib/parse_date.re" +#line 1428 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("americanshort | american"); @@ -11893,7 +11919,7 @@ yy700: TIMELIB_DEINIT; return TIMELIB_AMERICAN; } -#line 11899 "" +#line 11923 "" yy701: YYDEBUG(701, *YYCURSOR); yyaccept = 13; @@ -12127,7 +12153,7 @@ yy733: if (yych <= ':') goto yy737; yy734: YYDEBUG(734, *YYCURSOR); -#line 1699 "ext/date/lib/parse_date.re" +#line 1723 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("clf"); @@ -12147,7 +12173,7 @@ yy734: TIMELIB_DEINIT; return TIMELIB_CLF; } -#line 12153 "" +#line 12177 "" yy735: YYDEBUG(735, *YYCURSOR); yyaccept = 14; @@ -12767,7 +12793,7 @@ yy807: } yy808: YYDEBUG(808, *YYCURSOR); -#line 1432 "ext/date/lib/parse_date.re" +#line 1456 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("iso8601date2"); @@ -12780,7 +12806,7 @@ yy808: TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 12786 "" +#line 12810 "" yy809: YYDEBUG(809, *YYCURSOR); yych = *++YYCURSOR; @@ -12819,7 +12845,7 @@ yy815: YYDEBUG(815, *YYCURSOR); ++YYCURSOR; YYDEBUG(816, *YYCURSOR); -#line 1685 "ext/date/lib/parse_date.re" +#line 1709 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgtextreverse"); @@ -12832,7 +12858,7 @@ yy815: TIMELIB_DEINIT; return TIMELIB_PG_TEXT; } -#line 12838 "" +#line 12862 "" yy817: YYDEBUG(817, *YYCURSOR); yych = *++YYCURSOR; @@ -12997,7 +13023,7 @@ yy827: } yy828: YYDEBUG(828, *YYCURSOR); -#line 1720 "ext/date/lib/parse_date.re" +#line 1744 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("year4"); TIMELIB_INIT; @@ -13005,7 +13031,7 @@ yy828: TIMELIB_DEINIT; return TIMELIB_CLF; } -#line 13011 "" +#line 13035 "" yy829: YYDEBUG(829, *YYCURSOR); yych = *++YYCURSOR; @@ -13210,7 +13236,7 @@ yy837: } yy838: YYDEBUG(838, *YYCURSOR); -#line 1541 "ext/date/lib/parse_date.re" +#line 1565 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("datenodayrev"); @@ -13223,7 +13249,7 @@ yy838: TIMELIB_DEINIT; return TIMELIB_DATE_NO_DAY; } -#line 13229 "" +#line 13253 "" yy839: YYDEBUG(839, *YYCURSOR); yych = *++YYCURSOR; @@ -13444,7 +13470,7 @@ yy858: if (yych <= '7') goto yy861; yy859: YYDEBUG(859, *YYCURSOR); -#line 1652 "ext/date/lib/parse_date.re" +#line 1676 "ext/date/lib/parse_date.re" { timelib_sll w, d; DEBUG_OUTPUT("isoweek"); @@ -13462,7 +13488,7 @@ yy859: TIMELIB_DEINIT; return TIMELIB_ISO_WEEK; } -#line 13468 "" +#line 13492 "" yy860: YYDEBUG(860, *YYCURSOR); yych = *++YYCURSOR; @@ -13472,7 +13498,7 @@ yy861: YYDEBUG(861, *YYCURSOR); ++YYCURSOR; YYDEBUG(862, *YYCURSOR); -#line 1633 "ext/date/lib/parse_date.re" +#line 1657 "ext/date/lib/parse_date.re" { timelib_sll w, d; DEBUG_OUTPUT("isoweekday"); @@ -13490,7 +13516,7 @@ yy861: TIMELIB_DEINIT; return TIMELIB_ISO_WEEK; } -#line 13496 "" +#line 13520 "" yy863: YYDEBUG(863, *YYCURSOR); yych = *++YYCURSOR; @@ -13562,7 +13588,7 @@ yy865: } yy866: YYDEBUG(866, *YYCURSOR); -#line 1619 "ext/date/lib/parse_date.re" +#line 1643 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("pgydotd"); @@ -13575,7 +13601,7 @@ yy866: TIMELIB_DEINIT; return TIMELIB_PG_YEARDAY; } -#line 13581 "" +#line 13605 "" yy867: YYDEBUG(867, *YYCURSOR); yych = *++YYCURSOR; @@ -13678,7 +13704,7 @@ yy886: ++YYCURSOR; yy887: YYDEBUG(887, *YYCURSOR); -#line 1593 "ext/date/lib/parse_date.re" +#line 1617 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif"); @@ -13703,7 +13729,7 @@ yy887: TIMELIB_DEINIT; return TIMELIB_XMLRPC_SOAP; } -#line 13709 "" +#line 13733 "" yy888: YYDEBUG(888, *YYCURSOR); yych = *++YYCURSOR; @@ -13999,7 +14025,7 @@ yy892: } yy893: YYDEBUG(893, *YYCURSOR); -#line 1581 "ext/date/lib/parse_date.re" +#line 1605 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("datenocolon"); TIMELIB_INIT; @@ -14010,7 +14036,7 @@ yy893: TIMELIB_DEINIT; return TIMELIB_DATE_NOCOLON; } -#line 14016 "" +#line 14040 "" yy894: YYDEBUG(894, *YYCURSOR); yych = *++YYCURSOR; @@ -14932,7 +14958,7 @@ yy1017: } yy1018: YYDEBUG(1018, *YYCURSOR); -#line 1458 "ext/date/lib/parse_date.re" +#line 1482 "ext/date/lib/parse_date.re" { int length = 0; DEBUG_OUTPUT("gnudateshorter"); @@ -14945,7 +14971,7 @@ yy1018: TIMELIB_DEINIT; return TIMELIB_ISO_DATE; } -#line 14951 "" +#line 14975 "" yy1019: YYDEBUG(1019, *YYCURSOR); yyaccept = 22; @@ -16153,7 +16179,7 @@ yy1125: } yy1127: YYDEBUG(1127, *YYCURSOR); -#line 1338 "ext/date/lib/parse_date.re" +#line 1362 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("gnunocolon"); TIMELIB_INIT; @@ -16175,7 +16201,7 @@ yy1127: TIMELIB_DEINIT; return TIMELIB_GNU_NOCOLON; } -#line 16181 "" +#line 16205 "" yy1128: YYDEBUG(1128, *YYCURSOR); yych = *++YYCURSOR; @@ -16275,7 +16301,7 @@ yy1134: } yy1135: YYDEBUG(1135, *YYCURSOR); -#line 1384 "ext/date/lib/parse_date.re" +#line 1408 "ext/date/lib/parse_date.re" { int tz_not_found; DEBUG_OUTPUT("iso8601nocolon"); @@ -16294,7 +16320,7 @@ yy1135: TIMELIB_DEINIT; return TIMELIB_ISO_NOCOLON; } -#line 16300 "" +#line 16324 "" yy1136: YYDEBUG(1136, *YYCURSOR); yyaccept = 25; @@ -17270,7 +17296,7 @@ yy1178: } yy1179: YYDEBUG(1179, *YYCURSOR); -#line 1792 "ext/date/lib/parse_date.re" +#line 1816 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -17286,7 +17312,7 @@ yy1179: TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 17292 "" +#line 17316 "" yy1180: YYDEBUG(1180, *YYCURSOR); ++YYCURSOR; @@ -17352,7 +17378,7 @@ yy1188: YYDEBUG(1188, *YYCURSOR); ++YYCURSOR; YYDEBUG(1189, *YYCURSOR); -#line 1251 "ext/date/lib/parse_date.re" +#line 1275 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -17373,7 +17399,7 @@ yy1188: TIMELIB_DEINIT; return TIMELIB_WEEK_DAY_OF_MONTH; } -#line 17379 "" +#line 17403 "" yy1190: YYDEBUG(1190, *YYCURSOR); yyaccept = 26; @@ -17513,7 +17539,7 @@ yy1205: } yy1206: YYDEBUG(1206, *YYCURSOR); -#line 1768 "ext/date/lib/parse_date.re" +#line 1792 "ext/date/lib/parse_date.re" { timelib_sll i; int behavior = 0; @@ -17536,7 +17562,7 @@ yy1206: TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 17542 "" +#line 17566 "" yy1207: YYDEBUG(1207, *YYCURSOR); yych = *++YYCURSOR; @@ -20485,7 +20511,7 @@ yy1387: } yy1388: YYDEBUG(1388, *YYCURSOR); -#line 1228 "ext/date/lib/parse_date.re" +#line 1252 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("backof | frontof"); TIMELIB_INIT; @@ -20507,7 +20533,7 @@ yy1388: TIMELIB_DEINIT; return TIMELIB_LF_DAY_OF_MONTH; } -#line 20513 "" +#line 20537 "" yy1389: YYDEBUG(1389, *YYCURSOR); yyaccept = 28; @@ -20806,7 +20832,7 @@ yy1410: YYDEBUG(1410, *YYCURSOR); ++YYCURSOR; YYDEBUG(1411, *YYCURSOR); -#line 1211 "ext/date/lib/parse_date.re" +#line 1235 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("firstdayof | lastdayof"); TIMELIB_INIT; @@ -20822,7 +20848,7 @@ yy1410: TIMELIB_DEINIT; return TIMELIB_LF_DAY_OF_MONTH; } -#line 20828 "" +#line 20852 "" yy1412: YYDEBUG(1412, *YYCURSOR); yyaccept = 1; @@ -22344,7 +22370,7 @@ yy1483: if (yych <= '9') goto yy1483; yy1485: YYDEBUG(1485, *YYCURSOR); -#line 1145 "ext/date/lib/parse_date.re" +#line 1169 "ext/date/lib/parse_date.re" { timelib_ull i; @@ -22369,7 +22395,7 @@ yy1485: TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22375 "" +#line 22399 "" yy1486: YYDEBUG(1486, *YYCURSOR); ++YYCURSOR; @@ -22377,7 +22403,7 @@ yy1486: if (yych <= '9') goto yy1488; yy1487: YYDEBUG(1487, *YYCURSOR); -#line 1171 "ext/date/lib/parse_date.re" +#line 1195 "ext/date/lib/parse_date.re" { timelib_sll i; timelib_ull us; @@ -22416,7 +22442,7 @@ yy1487: TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22422 "" +#line 22446 "" yy1488: YYDEBUG(1488, *YYCURSOR); yych = *++YYCURSOR; @@ -22885,7 +22911,7 @@ yy1523: ++YYCURSOR; yy1524: YYDEBUG(1524, *YYCURSOR); -#line 1133 "ext/date/lib/parse_date.re" +#line 1157 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("tomorrow"); TIMELIB_INIT; @@ -22896,7 +22922,7 @@ yy1524: TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22902 "" +#line 22926 "" yy1525: YYDEBUG(1525, *YYCURSOR); yych = *++YYCURSOR; @@ -22931,7 +22957,7 @@ yy1526: } yy1527: YYDEBUG(1527, *YYCURSOR); -#line 1123 "ext/date/lib/parse_date.re" +#line 1147 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("midnight | today"); TIMELIB_INIT; @@ -22940,7 +22966,7 @@ yy1527: TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 22946 "" +#line 22970 "" yy1528: YYDEBUG(1528, *YYCURSOR); yych = *++YYCURSOR; @@ -25035,7 +25061,7 @@ yy1611: } yy1612: YYDEBUG(1612, *YYCURSOR); -#line 1102 "ext/date/lib/parse_date.re" +#line 1126 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("now"); TIMELIB_INIT; @@ -25043,7 +25069,7 @@ yy1612: TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 25049 "" +#line 25073 "" yy1613: YYDEBUG(1613, *YYCURSOR); yych = *++YYCURSOR; @@ -25182,7 +25208,7 @@ yy1619: } yy1620: YYDEBUG(1620, *YYCURSOR); -#line 1111 "ext/date/lib/parse_date.re" +#line 1135 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("noon"); TIMELIB_INIT; @@ -25193,7 +25219,7 @@ yy1620: TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 25199 "" +#line 25223 "" yy1621: YYDEBUG(1621, *YYCURSOR); yyaccept = 1; @@ -25726,7 +25752,7 @@ yy1642: ++YYCURSOR; yy1643: YYDEBUG(1643, *YYCURSOR); -#line 1090 "ext/date/lib/parse_date.re" +#line 1114 "ext/date/lib/parse_date.re" { DEBUG_OUTPUT("yesterday"); TIMELIB_INIT; @@ -25737,7 +25763,7 @@ yy1643: TIMELIB_DEINIT; return TIMELIB_RELATIVE; } -#line 25743 "" +#line 25767 "" yy1644: YYDEBUG(1644, *YYCURSOR); yyaccept = 1; @@ -25910,7 +25936,7 @@ yy1649: goto yy1643; } } -#line 1918 "ext/date/lib/parse_date.re" +#line 1942 "ext/date/lib/parse_date.re" } @@ -26618,15 +26644,18 @@ void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options) if (parsed->h == TIMELIB_UNSET) parsed->h = now->h != TIMELIB_UNSET ? now->h : 0; if (parsed->i == TIMELIB_UNSET) parsed->i = now->i != TIMELIB_UNSET ? now->i : 0; if (parsed->s == TIMELIB_UNSET) parsed->s = now->s != TIMELIB_UNSET ? now->s : 0; - if (parsed->z == TIMELIB_UNSET) parsed->z = now->z != TIMELIB_UNSET ? now->z : 0; - if (parsed->dst == TIMELIB_UNSET) parsed->dst = now->dst != TIMELIB_UNSET ? now->dst : 0; - if (!parsed->tz_abbr) { - parsed->tz_abbr = now->tz_abbr ? timelib_strdup(now->tz_abbr) : NULL; - } if (!parsed->tz_info) { parsed->tz_info = now->tz_info ? (!(options & TIMELIB_NO_CLONE) ? timelib_tzinfo_clone(now->tz_info) : now->tz_info) : NULL; + + if (parsed->z == TIMELIB_UNSET) parsed->z = now->z != TIMELIB_UNSET ? now->z : 0; + if (parsed->dst == TIMELIB_UNSET) parsed->dst = now->dst != TIMELIB_UNSET ? now->dst : 0; + + if (!parsed->tz_abbr) { + parsed->tz_abbr = now->tz_abbr ? timelib_strdup(now->tz_abbr) : NULL; + } } + if (parsed->zone_type == 0 && now->zone_type != 0) { parsed->zone_type = now->zone_type; /* parsed->tz_abbr = now->tz_abbr ? timelib_strdup(now->tz_abbr) : NULL; @@ -26638,7 +26667,7 @@ void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options) */ } -char *timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst) +const char *timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst) { const timelib_tz_lookup_table *tp; diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re index ee2d1d8f5bf..db5540a020e 100644 --- a/ext/date/lib/parse_date.re +++ b/ext/date/lib/parse_date.re @@ -360,7 +360,7 @@ static timelib_error_message *alloc_error_message(timelib_error_message **messag return *messages + (*count)++; } -static void add_warning(Scanner *s, int error_code, char *error) +static void add_warning(Scanner *s, int error_code, const char *error) { timelib_error_message *message = alloc_error_message(&s->errors->warning_messages, &s->errors->warning_count); @@ -370,7 +370,7 @@ static void add_warning(Scanner *s, int error_code, char *error) message->message = timelib_strdup(error); } -static void add_error(Scanner *s, int error_code, char *error) +static void add_error(Scanner *s, int error_code, const char *error) { timelib_error_message *message = alloc_error_message(&s->errors->error_messages, &s->errors->error_count); @@ -380,7 +380,7 @@ static void add_error(Scanner *s, int error_code, char *error) message->message = timelib_strdup(error); } -static void add_pbf_warning(Scanner *s, int error_code, char *error, const char *sptr, const char *cptr) +static void add_pbf_warning(Scanner *s, int error_code, const char *error, const char *sptr, const char *cptr) { timelib_error_message *message = alloc_error_message(&s->errors->warning_messages, &s->errors->warning_count); @@ -390,7 +390,7 @@ static void add_pbf_warning(Scanner *s, int error_code, char *error, const char message->message = timelib_strdup(error); } -static void add_pbf_error(Scanner *s, int error_code, char *error, const char *sptr, const char *cptr) +static void add_pbf_error(Scanner *s, int error_code, const char *error, const char *sptr, const char *cptr) { timelib_error_message *message = alloc_error_message(&s->errors->error_messages, &s->errors->error_count); @@ -484,6 +484,7 @@ static timelib_sll timelib_get_nr_ex(const char **ptr, int max_length, int *scan } ++*ptr; } + begin = *ptr; while ((**ptr >= '0') && (**ptr <= '9') && len < max_length) { ++*ptr; @@ -541,24 +542,49 @@ static timelib_sll timelib_get_frac_nr(const char **ptr) static timelib_ull timelib_get_signed_nr(Scanner *s, const char **ptr, int max_length) { - timelib_ull dir = 1; + char *str, *str_ptr; + timelib_sll tmp_nr = 0; + int len = 0; + + str = timelib_calloc(1, max_length + 2); // for sign and \0 + str_ptr = str; while (((**ptr < '0') || (**ptr > '9')) && (**ptr != '+') && (**ptr != '-')) { if (**ptr == '\0') { + add_error(s, TIMELIB_ERR_UNEXPECTED_DATA, "Found unexpected data"); + timelib_free(str); + return 0; + } + ++*ptr; + } + + if ((**ptr == '+') || (**ptr == '-')) { + *str_ptr = **ptr; + ++*ptr; + ++str_ptr; + } + + while (((**ptr < '0') || (**ptr > '9'))) { + if (**ptr == '\0') { + timelib_free(str); add_error(s, TIMELIB_ERR_UNEXPECTED_DATA, "Found unexpected data"); return 0; } ++*ptr; } - while (**ptr == '+' || **ptr == '-') - { - if (**ptr == '-') { - dir *= -1; - } + while ((**ptr >= '0') && (**ptr <= '9') && len < max_length) { + *str_ptr = **ptr; ++*ptr; + ++str_ptr; + ++len; } - return dir * timelib_get_nr(ptr, max_length); + + tmp_nr = strtoll(str, NULL, 10); + + timelib_free(str); + + return tmp_nr; } static timelib_sll timelib_lookup_relative_text(const char **ptr, int *behavior) @@ -2620,15 +2646,18 @@ void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options) if (parsed->h == TIMELIB_UNSET) parsed->h = now->h != TIMELIB_UNSET ? now->h : 0; if (parsed->i == TIMELIB_UNSET) parsed->i = now->i != TIMELIB_UNSET ? now->i : 0; if (parsed->s == TIMELIB_UNSET) parsed->s = now->s != TIMELIB_UNSET ? now->s : 0; - if (parsed->z == TIMELIB_UNSET) parsed->z = now->z != TIMELIB_UNSET ? now->z : 0; - if (parsed->dst == TIMELIB_UNSET) parsed->dst = now->dst != TIMELIB_UNSET ? now->dst : 0; - if (!parsed->tz_abbr) { - parsed->tz_abbr = now->tz_abbr ? timelib_strdup(now->tz_abbr) : NULL; - } if (!parsed->tz_info) { parsed->tz_info = now->tz_info ? (!(options & TIMELIB_NO_CLONE) ? timelib_tzinfo_clone(now->tz_info) : now->tz_info) : NULL; + + if (parsed->z == TIMELIB_UNSET) parsed->z = now->z != TIMELIB_UNSET ? now->z : 0; + if (parsed->dst == TIMELIB_UNSET) parsed->dst = now->dst != TIMELIB_UNSET ? now->dst : 0; + + if (!parsed->tz_abbr) { + parsed->tz_abbr = now->tz_abbr ? timelib_strdup(now->tz_abbr) : NULL; + } } + if (parsed->zone_type == 0 && now->zone_type != 0) { parsed->zone_type = now->zone_type; /* parsed->tz_abbr = now->tz_abbr ? timelib_strdup(now->tz_abbr) : NULL; @@ -2640,7 +2669,7 @@ void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options) */ } -char *timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst) +const char *timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst) { const timelib_tz_lookup_table *tp; diff --git a/ext/date/lib/parse_iso_intervals.c b/ext/date/lib/parse_iso_intervals.c index 8643859239b..6715d5cee52 100644 --- a/ext/date/lib/parse_iso_intervals.c +++ b/ext/date/lib/parse_iso_intervals.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.15.3 on Fri Jul 22 15:30:08 2022 */ +/* Generated by re2c 0.15.3 on Wed Sep 14 16:32:05 2022 */ #line 1 "ext/date/lib/parse_iso_intervals.re" /* * The MIT License (MIT) @@ -88,7 +88,7 @@ typedef struct _Scanner { int have_end_date; } Scanner; -static void add_error(Scanner *s, char *error) +static void add_error(Scanner *s, const char *error) { s->errors->error_count++; s->errors->error_messages = timelib_realloc(s->errors->error_messages, s->errors->error_count * sizeof(timelib_error_message)); diff --git a/ext/date/lib/parse_iso_intervals.re b/ext/date/lib/parse_iso_intervals.re index bd4015a323a..2a394156f98 100644 --- a/ext/date/lib/parse_iso_intervals.re +++ b/ext/date/lib/parse_iso_intervals.re @@ -86,7 +86,7 @@ typedef struct _Scanner { int have_end_date; } Scanner; -static void add_error(Scanner *s, char *error) +static void add_error(Scanner *s, const char *error) { s->errors->error_count++; s->errors->error_messages = timelib_realloc(s->errors->error_messages, s->errors->error_count * sizeof(timelib_error_message)); diff --git a/ext/date/lib/parse_tz.c b/ext/date/lib/parse_tz.c index e41315efdbf..c7f93580d72 100644 --- a/ext/date/lib/parse_tz.c +++ b/ext/date/lib/parse_tz.c @@ -910,21 +910,42 @@ timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo * return tmp; } +int timelib_get_time_zone_offset_info(timelib_sll ts, timelib_tzinfo *tz, int32_t* offset, timelib_sll* transition_time, unsigned int* is_dst) +{ + ttinfo *to; + timelib_sll tmp_transition_time; + + if (tz == NULL) { + return 0; + } + + if ((to = timelib_fetch_timezone_offset(tz, ts, &tmp_transition_time))) { + if (offset) { + *offset = to->offset; + } + if (is_dst) { + *is_dst = to->isdst; + } + if (transition_time) { + *transition_time = tmp_transition_time; + } + return 1; + } + return 0; +} + timelib_sll timelib_get_current_offset(timelib_time *t) { - timelib_time_offset *gmt_offset; - timelib_sll retval; - switch (t->zone_type) { case TIMELIB_ZONETYPE_ABBR: case TIMELIB_ZONETYPE_OFFSET: return t->z + (t->dst * 3600); - case TIMELIB_ZONETYPE_ID: - gmt_offset = timelib_get_time_zone_info(t->sse, t->tz_info); - retval = gmt_offset->offset; - timelib_time_offset_dtor(gmt_offset); - return retval; + case TIMELIB_ZONETYPE_ID: { + int32_t offset = 0; + timelib_get_time_zone_offset_info(t->sse, t->tz_info, &offset, NULL, NULL); + return offset; + } default: return 0; diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h index 7751ed218e4..3b559b95f47 100644 --- a/ext/date/lib/timelib.h +++ b/ext/date/lib/timelib.h @@ -30,9 +30,9 @@ # include "timelib_config.h" #endif -#define TIMELIB_VERSION 202201 -#define TIMELIB_EXTENDED_VERSION 20220101 -#define TIMELIB_ASCII_VERSION "2022.01" +#define TIMELIB_VERSION 202202 +#define TIMELIB_EXTENDED_VERSION 20220102 +#define TIMELIB_ASCII_VERSION "2022.02" #include #include @@ -342,10 +342,10 @@ typedef struct _timelib_error_container { } timelib_error_container; typedef struct _timelib_tz_lookup_table { - char *name; + const char *name; int type; float gmtoffset; - char *full_tz_name; + const char *full_tz_name; } timelib_tz_lookup_table; typedef struct _timelib_tzdb_index_entry { @@ -354,7 +354,7 @@ typedef struct _timelib_tzdb_index_entry { } timelib_tzdb_index_entry; typedef struct _timelib_tzdb { - char *version; + const char *version; int index_size; const timelib_tzdb_index_entry *index; const unsigned char *data; @@ -584,7 +584,7 @@ void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options); * * The returned char* is not duplicated, and should not be freed. */ -char *timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst); +const char *timelib_timezone_id_from_abbr(const char *abbr, timelib_long gmtoffset, int isdst); /* Returns an array of known time zone abbreviations * @@ -793,6 +793,19 @@ int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz); */ timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz); +/** + * Returns offset information with time zone 'tz' for the time stamp 'ts'. + * + * The returned information contains: the offset in seconds East of UTC (in + * the output parameter 'offset'), whether DST is active (in the output + * parameter 'is_dst'), and the transition time that got to this state (in + * the output parameter 'transition_time'); if NULL is passed, the value is + * not retrieved + * + * Returns 1 if successful, 0 for failure. + */ +int timelib_get_time_zone_offset_info(timelib_sll ts, timelib_tzinfo *tz, int32_t* offset, timelib_sll* transition_time, unsigned int* is_dst); + /** * Returns the UTC offset currently applicable for the information stored in 't'. * diff --git a/ext/date/lib/timelib_private.h b/ext/date/lib/timelib_private.h index 2015a15dbf7..65ec6b014b8 100644 --- a/ext/date/lib/timelib_private.h +++ b/ext/date/lib/timelib_private.h @@ -112,6 +112,20 @@ m = NULL; \ } +#if defined (__GNUC__) +# define TIMELIB_GNUC_CHECK_VERSION(major, minor) \ + ((__GNUC__ > (major)) || \ + ((__GNUC__ == (major)) && (__GNUC_MINOR__ >= (minor)))) +#else +# define TIMELIB_GNUC_CHECK_VERSION(major, minor) 0 +#endif + +#if TIMELIB_GNUC_CHECK_VERSION(7, 0) +# define TIMELIB_BREAK_INTENTIONALLY_MISSING __attribute__ ((fallthrough)); +#else +# define TIMELIB_BREAK_INTENTIONALLY_MISSING +#endif + struct _ttinfo { int32_t offset; diff --git a/ext/date/lib/tm2unixtime.c b/ext/date/lib/tm2unixtime.c index 7740b25e97e..08332bb4706 100644 --- a/ext/date/lib/tm2unixtime.c +++ b/ext/date/lib/tm2unixtime.c @@ -104,9 +104,10 @@ static void do_range_limit_days_relative(timelib_sll *base_y, timelib_sll *base_ static int do_range_limit_days(timelib_sll *y, timelib_sll *m, timelib_sll *d) { timelib_sll leapyear; - timelib_sll days_this_month; - timelib_sll last_month, last_year; - timelib_sll days_last_month; + timelib_sll previous_month, previous_year; + timelib_sll days_in_previous_month; + int retval = 0; + int *days_per_month_current_year; /* can jump an entire leap year period quickly */ if (*d >= DAYS_PER_ERA || *d <= -DAYS_PER_ERA) { @@ -117,29 +118,29 @@ static int do_range_limit_days(timelib_sll *y, timelib_sll *m, timelib_sll *d) do_range_limit(1, 13, 12, m, y); leapyear = timelib_is_leap(*y); - days_this_month = leapyear ? days_in_month_leap[*m] : days_in_month[*m]; - last_month = (*m) - 1; + days_per_month_current_year = leapyear ? days_in_month_leap : days_in_month; - if (last_month < 1) { - last_month += 12; - last_year = (*y) - 1; - } else { - last_year = (*y); - } - leapyear = timelib_is_leap(last_year); - days_last_month = leapyear ? days_in_month_leap[last_month] : days_in_month[last_month]; + while (*d <= 0 && *m > 0) { + previous_month = (*m) - 1; + if (previous_month < 1) { + previous_month += 12; + previous_year = (*y) - 1; + } else { + previous_year = (*y); + } + leapyear = timelib_is_leap(previous_year); + days_in_previous_month = leapyear ? days_in_month_leap[previous_month] : days_in_month[previous_month]; - if (*d <= 0) { - *d += days_last_month; + *d += days_in_previous_month; (*m)--; - return 1; + retval = 1; } - if (*d > days_this_month) { - *d -= days_this_month; + while (*d > 0 && *m <= 12 && *d > days_per_month_current_year[*m]) { + *d -= days_per_month_current_year[*m]; (*m)++; - return 1; + retval = 1; } - return 0; + return retval; } static void do_adjust_for_weekday(timelib_time* time) @@ -372,11 +373,15 @@ static void do_adjust_timezone(timelib_time *tz, timelib_tzinfo *tzi) case TIMELIB_ZONETYPE_ID: tzi = tz->tz_info; - /* Break intentionally missing */ + TIMELIB_BREAK_INTENTIONALLY_MISSING default: { /* No timezone in struct, fallback to reference if possible */ - timelib_time_offset *current, *after; + int32_t current_offset = 0; + timelib_sll current_transition_time = 0; + unsigned int current_is_dst = 0; + int32_t after_offset = 0; + timelib_sll after_transition_time = 0; timelib_sll adjustment; int in_transition; int32_t actual_offset; @@ -386,49 +391,47 @@ static void do_adjust_timezone(timelib_time *tz, timelib_tzinfo *tzi) return; } - current = timelib_get_time_zone_info(tz->sse, tzi); - after = timelib_get_time_zone_info(tz->sse - current->offset, tzi); - actual_offset = after->offset; - actual_transition_time = after->transition_time; - if (current->offset == after->offset && tz->have_zone) { + timelib_get_time_zone_offset_info(tz->sse, tzi, ¤t_offset, ¤t_transition_time, ¤t_is_dst); + timelib_get_time_zone_offset_info(tz->sse - current_offset, tzi, &after_offset, &after_transition_time, NULL); + actual_offset = after_offset; + actual_transition_time = after_transition_time; + if (current_offset == after_offset && tz->have_zone) { /* Make sure we're not missing a DST change because we don't know the actual offset yet */ - if (current->offset >= 0 && tz->dst && !current->is_dst) { + if (current_offset >= 0 && tz->dst && !current_is_dst) { /* Timezone or its DST at or east of UTC, so the local time, interpreted as UTC, leaves DST (as defined in the actual timezone) before the actual local time */ - timelib_time_offset *earlier; - earlier = timelib_get_time_zone_info(tz->sse - current->offset - 7200, tzi); - if ((earlier->offset != after->offset) && (tz->sse - earlier->offset < after->transition_time)) { + int32_t earlier_offset; + timelib_sll earlier_transition_time; + timelib_get_time_zone_offset_info(tz->sse - current_offset - 7200, tzi, &earlier_offset, &earlier_transition_time, NULL); + if ((earlier_offset != after_offset) && (tz->sse - earlier_offset < after_transition_time)) { /* Looking behind a bit clarified the actual offset to use */ - actual_offset = earlier->offset; - actual_transition_time = earlier->transition_time; + actual_offset = earlier_offset; + actual_transition_time = earlier_transition_time; } - timelib_time_offset_dtor(earlier); - } else if (current->offset <= 0 && current->is_dst && !tz->dst) { + } else if (current_offset <= 0 && current_is_dst && !tz->dst) { /* Timezone west of UTC, so the local time, interpreted as UTC, leaves DST (as defined in the actual timezone) after the actual local time */ - timelib_time_offset *later; - later = timelib_get_time_zone_info(tz->sse - current->offset + 7200, tzi); - if ((later->offset != after->offset) && (tz->sse - later->offset >= later->transition_time)) { + int32_t later_offset; + timelib_sll later_transition_time; + timelib_get_time_zone_offset_info(tz->sse - current_offset + 7200, tzi, &later_offset, &later_transition_time, NULL); + if ((later_offset != after_offset) && (tz->sse - later_offset >= later_transition_time)) { /* Looking ahead a bit clarified the actual offset to use */ - actual_offset = later->offset; - actual_transition_time = later->transition_time; + actual_offset = later_offset; + actual_transition_time = later_transition_time; } - timelib_time_offset_dtor(later); } } tz->is_localtime = 1; in_transition = ( - ((tz->sse - actual_offset) >= (actual_transition_time + (current->offset - actual_offset))) && + ((tz->sse - actual_offset) >= (actual_transition_time + (current_offset - actual_offset))) && ((tz->sse - actual_offset) < actual_transition_time) ); - if ((current->offset != actual_offset) && !in_transition) { + if ((current_offset != actual_offset) && !in_transition) { adjustment = -actual_offset; } else { - adjustment = -current->offset; + adjustment = -current_offset; } - timelib_time_offset_dtor(current); - timelib_time_offset_dtor(after); tz->sse += adjustment; timelib_set_timezone(tz, tzi); diff --git a/ext/date/lib/unixtime2tm.c b/ext/date/lib/unixtime2tm.c index f8ea9216633..30b3d00c7f4 100644 --- a/ext/date/lib/unixtime2tm.c +++ b/ext/date/lib/unixtime2tm.c @@ -97,11 +97,10 @@ void timelib_update_from_sse(timelib_time *tm) } case TIMELIB_ZONETYPE_ID: { - timelib_time_offset *gmt_offset; + int32_t offset = 0; - gmt_offset = timelib_get_time_zone_info(tm->sse, tm->tz_info); - timelib_unixtime2gmt(tm, tm->sse + gmt_offset->offset); - timelib_time_offset_dtor(gmt_offset); + timelib_get_time_zone_offset_info(tm->sse, tm->tz_info, &offset, NULL, NULL); + timelib_unixtime2gmt(tm, tm->sse + offset); goto cleanup; } From f8b27c73c9ba9d747f86c617df93ae46b3b898e2 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Wed, 14 Sep 2022 16:40:06 +0100 Subject: [PATCH 2/4] Use 'const' for fixed API --- ext/date/php_date.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 321817235dd..fbdf0082e80 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -3786,7 +3786,7 @@ PHP_FUNCTION(timezone_name_get) PHP_FUNCTION(timezone_name_from_abbr) { zend_string *abbr; - char *tzid; + const char *tzid; zend_long gmtoffset = -1; zend_long isdst = -1; From 7448ee365c00054bcbf2c0493e6cca152865ba21 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Wed, 14 Sep 2022 16:44:46 +0100 Subject: [PATCH 3/4] Add test case for timelib #124 --- ext/date/tests/bug40861.phpt | 2 +- ext/date/tests/gh-124.phpt | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 ext/date/tests/gh-124.phpt diff --git a/ext/date/tests/bug40861.phpt b/ext/date/tests/bug40861.phpt index d4ef96198c7..224d8eb0a71 100644 --- a/ext/date/tests/bug40861.phpt +++ b/ext/date/tests/bug40861.phpt @@ -28,6 +28,6 @@ echo $result . "\n"; ?> --EXPECT-- 2000-01-01 13:00:00 +2000-01-01 13:00:00 2000-01-01 11:00:00 2000-01-01 13:00:00 -2000-01-01 13:00:00 diff --git a/ext/date/tests/gh-124.phpt b/ext/date/tests/gh-124.phpt new file mode 100644 index 00000000000..432bf06e808 --- /dev/null +++ b/ext/date/tests/gh-124.phpt @@ -0,0 +1,21 @@ +--TEST-- +Test for timelib #124: Problem with large negative timestamps +--INI-- +date.timezone=UTC +--FILE-- +getTimestamp()); +var_dump((new DateTime('-292277022657-01-27 08:29:52 UTC'))->getTimestamp()); +var_dump((new DateTime('-292277022657-01-27 08:29:53 UTC'))->getTimestamp()); + +var_dump((new DateTime("@9223372036854775807"))->getTimestamp()); +var_dump((new DateTime('+292277026596-12-04 15:30:07 UTC'))->getTimestamp()); +echo (new DateTime('+2512370164-01-01 00:00:00Z'))->format(DATE_RFC3339_EXTENDED); +?> +--EXPECT-- +int(-9223372036854775808) +int(-9223372036854775808) +int(-9223372036854775807) +int(9223372036854775807) +int(9223372036854775807) +2512370164-01-01T00:00:00.000+00:00 From 0f9351669b44f5bcbd44c5e05f60d292f8137f7d Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Wed, 14 Sep 2022 16:44:54 +0100 Subject: [PATCH 4/4] Update NEWS --- NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 33692a18181..514c475d910 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.0RC3 +- Date: + . Fixed bug with parsing large negative numbers with the @ notation. (Derick) + - Sockets: . Fixed socket constants regression as of PHP 8.2.0beta3. (Bruce Dou)