diff --git a/tests/c/diff.cpp b/tests/c/diff.cpp index b4cfbbc..77c9b1a 100644 --- a/tests/c/diff.cpp +++ b/tests/c/diff.cpp @@ -428,3 +428,54 @@ TEST(timelib_diff, test_time_fall_type2_stsec_type2_dtsec) test_parse("America/New_York", "2010-11-07 01:00:00 EST", "2010-11-07 01:59:59 EDT"); CHECKDIFF(0, 0, 0, 0, 0, 1, 0); } + + +TEST(timelib_diff, php_gh13857a) +{ + test_parse("Asia/Tokyo", "UTC", "2024-04-01 00:49:22", "2024-03-31 23:48:22"); + CHECKDIFF(0, 0, 0, 7, 59, 0, 0); +} + +TEST(timelib_diff, php_gh13857b) +{ + test_parse("Asia/Tokyo", "UTC", "2024-01-01 00:49:22", "2023-12-31 23:48:22"); + CHECKDIFF(0, 0, 0, 7, 59, 0, 0); +} + +TEST(timelib_diff, php_gh13857c) +{ + test_parse("Asia/Tokyo", "UTC", "2023-12-01 00:49:22", "2023-11-30 23:48:22"); + CHECKDIFF(0, 0, 0, 7, 59, 0, 0); +} + +TEST(timelib_diff, php_gh13857d) +{ + test_parse("Asia/Tokyo", "UTC", "2024-02-01 00:49:22", "2024-01-31 23:48:22"); + CHECKDIFF(0, 0, 0, 7, 59, 0, 0); +} + + +TEST(timelib_diff, php_gh13857e) +{ + test_parse("UTC", "Asia/Tokyo", "2024-03-31 23:48:22", "2024-04-01 00:49:22"); + CHECKDIFF(0, 0, 0, 7, 59, 0, 0); +} + +TEST(timelib_diff, php_gh13857f) +{ + test_parse("UTC", "Asia/Tokyo", "2023-12-31 23:48:22", "2024-01-01 00:49:22"); + CHECKDIFF(0, 0, 0, 7, 59, 0, 0); +} + +TEST(timelib_diff, php_gh13857g) +{ + test_parse("UTC", "Asia/Tokyo", "2023-11-30 23:48:22", "2023-12-01 00:49:22"); + CHECKDIFF(0, 0, 0, 7, 59, 0, 0); +} + +TEST(timelib_diff, php_gh13857h) +{ + test_parse("UTC", "Asia/Tokyo", "2024-01-31 23:48:22", "2024-02-01 00:49:22"); + CHECKDIFF(0, 0, 0, 7, 59, 0, 0); +} + diff --git a/tm2unixtime.c b/tm2unixtime.c index f13a941..b35eb70 100644 --- a/tm2unixtime.c +++ b/tm2unixtime.c @@ -81,7 +81,20 @@ static void do_range_limit_days_relative(timelib_sll *base_y, timelib_sll *base_ /* printf( "S: Y%d M%d %d %d %d %d\n", year, month, *y, *m, *d, days); */ + if (*y == -1 && *m == 11 && *d == 31) { + (*y) = 0; + (*m) = 0; + (*d) = 0; + } if (!invert) { + if (*m == -1) { + leapyear = timelib_is_leap(year); + days = leapyear ? days_in_month_leap[month] : days_in_month[month]; + if (*d >= days) { + *d -= days; + (*m)++; + } + } while (*d < 0) { dec_month(&year, &month); leapyear = timelib_is_leap(year); @@ -93,6 +106,14 @@ static void do_range_limit_days_relative(timelib_sll *base_y, timelib_sll *base_ (*m)--; } } else { + if (*m == -1 && month > 1) { + leapyear = timelib_is_leap(year); + days = leapyear ? days_in_month_leap[month + *m] : days_in_month[month + *m]; + if (*d >= days) { + *d -= days; + (*m)++; + } + } while (*d < 0) { leapyear = timelib_is_leap(year); days = leapyear ? days_in_month_leap[month] : days_in_month[month]; @@ -191,7 +212,6 @@ void timelib_do_rel_normalize(timelib_time *base, timelib_rel_time *rt) do_range_limit(0, 60, 60, &rt->s, &rt->i); do_range_limit(0, 60, 60, &rt->i, &rt->h); do_range_limit(0, 24, 24, &rt->h, &rt->d); - do_range_limit(0, 12, 12, &rt->m, &rt->y); do_range_limit_days_relative(&base->y, &base->m, &rt->y, &rt->m, &rt->d, rt->invert); do_range_limit(0, 12, 12, &rt->m, &rt->y);