From 66ea59e38eb727b76fa49dfbb45ce3acf79ddab6 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Sun, 8 Aug 2021 17:22:06 +0100 Subject: [PATCH] Import timelib 2021.07 Fixes: - Bug #80998 (Missing second with inverted interval). (Derick) - Bug #81106 (Regression in 8.1: add() now truncate ->f). (Derick) --- NEWS | 2 ++ ext/date/lib/interval.c | 15 +++++++++++++++ ext/date/lib/parse_posix.c | 20 +++++++------------- ext/date/lib/timelib.h | 18 +++++++++++++++--- ext/date/tests/bug80998.phpt | 12 ++++++++++++ ext/date/tests/bug81106.phpt | 11 +++++++++++ 6 files changed, 62 insertions(+), 16 deletions(-) create mode 100644 ext/date/tests/bug80998.phpt create mode 100644 ext/date/tests/bug81106.phpt diff --git a/NEWS b/NEWS index 9a7fe434670..b5e06b21432 100644 --- a/NEWS +++ b/NEWS @@ -6,8 +6,10 @@ PHP NEWS . Fixed bug #79580 (date_create_from_format misses leap year). (Derick) . Fixed bug #80974 (Wrong diff between 2 dates in different timezones). (Derick) + . Fixed bug #80998 (Missing second with inverted interval). (Derick) . Fixed bug #81097 (DateTimeZone silently falls back to UTC when providing an offset with seconds). (Derick) + . Fixed bug #81106 (Regression in 8.1: add() now truncate ->f). (Derick) . Fixed bug #81273 (Date interval calculation not correct). (Derick) diff --git a/ext/date/lib/interval.c b/ext/date/lib/interval.c index 96c8140e449..5c2d35d8f23 100644 --- a/ext/date/lib/interval.c +++ b/ext/date/lib/interval.c @@ -207,6 +207,19 @@ timelib_time *timelib_sub(timelib_time *old_time, timelib_rel_time *interval) return t; } +static void do_range_limit(timelib_sll start, timelib_sll end, timelib_sll adj, timelib_sll *a, timelib_sll *b) +{ + if (*a < start) { + *b -= (start - *a - 1) / adj + 1; + *a += adj * ((start - *a - 1) / adj + 1); + } + if (*a >= end) { + *b += *a / adj; + *a -= adj * (*a / adj); + } +} + + timelib_time *timelib_add_wall(timelib_time *old_time, timelib_rel_time *interval) { int bias = 1; @@ -232,6 +245,7 @@ timelib_time *timelib_add_wall(timelib_time *old_time, timelib_rel_time *interva timelib_update_ts(t, NULL); } + do_range_limit(0, 1000000, 1000000, &interval->us, &interval->s); t->sse += bias * timelib_hms_to_seconds(interval->h, interval->i, interval->s); t->us += interval->us * bias; timelib_do_normalize(t); @@ -271,6 +285,7 @@ timelib_time *timelib_sub_wall(timelib_time *old_time, timelib_rel_time *interva timelib_update_ts(t, NULL); } + do_range_limit(0, 1000000, 1000000, &interval->us, &interval->s); t->sse -= bias * timelib_hms_to_seconds(interval->h, interval->i, interval->s); t->us -= interval->us * bias; timelib_do_normalize(t); diff --git a/ext/date/lib/parse_posix.c b/ext/date/lib/parse_posix.c index 13b6767dafc..204b328b890 100644 --- a/ext/date/lib/parse_posix.c +++ b/ext/date/lib/parse_posix.c @@ -405,12 +405,6 @@ timelib_posix_str* timelib_parse_posix_str(const char *posix) return tmp; } -typedef struct _posix_transitions { - size_t count; - timelib_sll times[6]; - timelib_sll types[6]; -} posix_transitions; - static const int month_lengths[2][MONTHS_PER_YEAR] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, // normal year { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } // leap year @@ -503,7 +497,7 @@ timelib_sll timelib_ts_at_start_of_year(timelib_sll year) ); } -static void calc_transitions_for_year(timelib_tzinfo *tz, timelib_sll year, posix_transitions *transitions) +void timelib_get_transitions_for_year(timelib_tzinfo *tz, timelib_sll year, timelib_posix_transitions *transitions) { timelib_sll trans_begin; /* Since start of the year */ timelib_sll trans_end; @@ -536,9 +530,9 @@ static void calc_transitions_for_year(timelib_tzinfo *tz, timelib_sll year, posi ttinfo* timelib_fetch_posix_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib_sll *transition_time) { - timelib_sll year; - timelib_time dummy; - posix_transitions transitions = { 0 }; + timelib_sll year; + timelib_time dummy; + timelib_posix_transitions transitions = { 0 }; size_t i; /* If there is no second (dst_end) information, the UTC offset is valid for the whole year, so no need to @@ -555,9 +549,9 @@ ttinfo* timelib_fetch_posix_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, year = dummy.y; /* Calculate transition times for 'year-1', 'year', and 'year+1' */ - calc_transitions_for_year(tz, year - 1, &transitions); - calc_transitions_for_year(tz, year, &transitions); - calc_transitions_for_year(tz, year + 1, &transitions); + timelib_get_transitions_for_year(tz, year - 1, &transitions); + timelib_get_transitions_for_year(tz, year, &transitions); + timelib_get_transitions_for_year(tz, year + 1, &transitions); /* Check where the 'ts' falls in the 4 transitions */ for (i = 1; i < transitions.count; i++) { diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h index b6e84eb7abb..dc9056572a0 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 202106 -#define TIMELIB_EXTENDED_VERSION 20210601 -#define TIMELIB_ASCII_VERSION "2021.06" +#define TIMELIB_VERSION 202107 +#define TIMELIB_EXTENDED_VERSION 20210701 +#define TIMELIB_ASCII_VERSION "2021.07" #include #include @@ -180,6 +180,12 @@ typedef struct _timelib_posix_str int type_index_dst_type; // index into tz->type } timelib_posix_str; +typedef struct _timelib_posix_transitions { + size_t count; + timelib_sll times[6]; + timelib_sll types[6]; +} timelib_posix_transitions; + typedef struct _timelib_tzinfo { char *name; @@ -1046,6 +1052,12 @@ void timelib_posix_str_dtor(timelib_posix_str *ps); timelib_posix_str* timelib_parse_posix_str(const char *posix); +/** + * Calculate the two yearly to/from DST + */ +void timelib_get_transitions_for_year(timelib_tzinfo *tz, timelib_sll year, timelib_posix_transitions *transitions); + + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/ext/date/tests/bug80998.phpt b/ext/date/tests/bug80998.phpt new file mode 100644 index 00000000000..1ca9c57f408 --- /dev/null +++ b/ext/date/tests/bug80998.phpt @@ -0,0 +1,12 @@ +--TEST-- +Bug #80998: Missing second with inverted interval +--FILE-- +f = 0.999999; +$interval->invert = 1; +$date->add($interval); +$string = $date->format('Y-m-d H:i:s.u'); +?> +--EXPECT-- diff --git a/ext/date/tests/bug81106.phpt b/ext/date/tests/bug81106.phpt new file mode 100644 index 00000000000..c8890da6bc0 --- /dev/null +++ b/ext/date/tests/bug81106.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #81106: Regression in 8.1: add() now truncate ->f +--FILE-- +f = 1.234; + +echo (new DateTimeImmutable('2000-01-01 00:00:00'))->add($dateInterval)->format('Y-m-d H:i:s.u'); +?> +--EXPECT-- +2000-01-01 00:00:01.234000