diff --git a/ext/date/lib/unixtime2tm.c b/ext/date/lib/unixtime2tm.c index 43bfe818f55d7..4c4222665127c 100644 --- a/ext/date/lib/unixtime2tm.c +++ b/ext/date/lib/unixtime2tm.c @@ -32,80 +32,69 @@ static int month_tab[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 3 /* Converts a Unix timestamp value into broken down time, in GMT */ void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts) { - timelib_sll days, remainder, tmp_days; + timelib_sll days = 0, remainder = 0; timelib_sll cur_year = 1970; timelib_sll i; timelib_sll hours, minutes, seconds; int *months; - days = ts / SECS_PER_DAY; - remainder = ts - (days * SECS_PER_DAY); + remainder = ts; + days = remainder / SECS_PER_DAY; + remainder %= SECS_PER_DAY; + if (ts < 0 && remainder == 0) { days++; remainder -= SECS_PER_DAY; } - TIMELIB_DEBUG(printf("days=%lld, rem=%lld\n", days, remainder);); - if (ts >= 0) { - tmp_days = days + 1; + if (days >= DAYS_PER_LYEAR_PERIOD || days <= -DAYS_PER_LYEAR_PERIOD) { + cur_year += days / DAYS_PER_LYEAR_PERIOD * YEARS_PER_LYEAR_PERIOD; + days %= DAYS_PER_LYEAR_PERIOD; + } - if (tmp_days > DAYS_PER_LYEAR_PERIOD || tmp_days <= -DAYS_PER_LYEAR_PERIOD) { - cur_year += YEARS_PER_LYEAR_PERIOD * (tmp_days / DAYS_PER_LYEAR_PERIOD); - tmp_days -= DAYS_PER_LYEAR_PERIOD * (tmp_days / DAYS_PER_LYEAR_PERIOD); - } + TIMELIB_DEBUG(printf("days=%lld, year=%lld\n", days, cur_year);); - while (tmp_days >= DAYS_PER_LYEAR) { + if (ts >= 0) { + days++; + + while (days >= DAYS_PER_LYEAR) { cur_year++; if (timelib_is_leap(cur_year)) { - tmp_days -= DAYS_PER_LYEAR; + days -= DAYS_PER_LYEAR; } else { - tmp_days -= DAYS_PER_YEAR; + days -= DAYS_PER_YEAR; } } - } else { - tmp_days = days; - - /* Guess why this might be for, it has to do with a pope ;-). It's also - * only valid for Great Brittain and it's colonies. It needs fixing for - * other locales. *sigh*, why is this crap so complex! */ - /* - if (ts <= TIMELIB_LL_CONST(-6857352000)) { - tmp_days -= 11; - } - */ + } + else { + remainder += SECS_PER_DAY; - while (tmp_days <= 0) { - if (tmp_days < -1460970) { - cur_year -= 4000; - TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year);); - tmp_days += 1460970; + while (days <= 0) { + cur_year--; + if (timelib_is_leap(cur_year)) { + days += DAYS_PER_LYEAR; } else { - cur_year--; - TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year);); - if (timelib_is_leap(cur_year)) { - tmp_days += DAYS_PER_LYEAR; - } else { - tmp_days += DAYS_PER_YEAR; - } + days += DAYS_PER_YEAR; } } - remainder += SECS_PER_DAY; } - TIMELIB_DEBUG(printf("tmp_days=%lld, year=%lld\n", tmp_days, cur_year);); + + TIMELIB_DEBUG(printf("days=%lld, year=%lld\n", days, cur_year);); months = timelib_is_leap(cur_year) ? month_tab_leap : month_tab; if (timelib_is_leap(cur_year) && cur_year < 1970) { - tmp_days--; + days--; } + i = 11; while (i > 0) { TIMELIB_DEBUG(printf("month=%lld (%d)\n", i, months[i]);); - if (tmp_days > months[i]) { + if (days > months[i]) { break; } i--; } - TIMELIB_DEBUG(printf("A: ts=%lld, year=%lld, month=%lld, day=%lld,", ts, cur_year, i + 1, tmp_days - months[i]);); + TIMELIB_DEBUG(printf("A: ts=%lld, year=%lld, month=%lld, day=%lld,", ts, cur_year, i + 1, days - months[i]);); /* That was the date, now we do the tiiiime */ hours = remainder / 3600; @@ -115,7 +104,7 @@ void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts) tm->y = cur_year; tm->m = i + 1; - tm->d = tmp_days - months[i]; + tm->d = days - months[i]; tm->h = hours; tm->i = minutes; tm->s = seconds; diff --git a/ext/date/tests/bug75088_date.phpt b/ext/date/tests/bug75088_date.phpt new file mode 100644 index 0000000000000..15edbca9c0921 --- /dev/null +++ b/ext/date/tests/bug75088_date.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #75088 getTransitions is slow with large values +--FILE-- + +==DONE== +--EXPECT-- +-9223372036854775808: -292277022657-01-27 08:29:52 +-2208988800: 1900-01-01 00:00:00 +-2203891200: 1900-03-01 00:00:00 +0: 1970-01-01 00:00:00 +946684800: 2000-01-01 00:00:00 +951782400: 2000-02-29 00:00:00 +1078012800: 2004-02-29 00:00:00 +3191032750586206520: 101119804369-12-31 02:15:20 +5278333347477533876: 167263727169-12-31 08:17:56 +6202182859306740885: 196539352769-12-31 18:14:45 +7060696112971042445: 223744554769-12-31 17:34:05 +9223372036854775807: 292277026596-12-04 15:30:07 +==DONE== diff --git a/ext/date/tests/bug75088_timezone_transitions_get.phpt b/ext/date/tests/bug75088_timezone_transitions_get.phpt new file mode 100644 index 0000000000000..9e89f8e88914c --- /dev/null +++ b/ext/date/tests/bug75088_timezone_transitions_get.phpt @@ -0,0 +1,288 @@ +--TEST-- +Bug #75088 getTransitions is slow with large values +--FILE-- +getTransitions($timestamp) as $transition) { + printf("%d: %s\n", $transition['ts'], $transition['time']); + } +} + +?> +==DONE== +--EXPECT-- +-9223372036854775808: -292277022657-01-27T08:29:52+0000 +-2147483648: 1901-12-13T20:45:52+0000 +-1693706400: 1916-04-30T22:00:00+0000 +-1680483600: 1916-09-30T23:00:00+0000 +-1663455600: 1917-04-16T01:00:00+0000 +-1650150000: 1917-09-17T01:00:00+0000 +-1632006000: 1918-04-15T01:00:00+0000 +-1618700400: 1918-09-16T01:00:00+0000 +-938905200: 1940-04-01T01:00:00+0000 +-857257200: 1942-11-02T01:00:00+0000 +-844556400: 1943-03-29T01:00:00+0000 +-828226800: 1943-10-04T01:00:00+0000 +-812502000: 1944-04-03T01:00:00+0000 +-796777200: 1944-10-02T01:00:00+0000 +-781052400: 1945-04-02T01:00:00+0000 +-776563200: 1945-05-24T00:00:00+0000 +-765936000: 1945-09-24T00:00:00+0000 +-761180400: 1945-11-18T01:00:00+0000 +-757386000: 1945-12-31T23:00:00+0000 +-748479600: 1946-04-14T01:00:00+0000 +-733273200: 1946-10-07T01:00:00+0000 +-717631200: 1947-04-06T02:00:00+0000 +-714610800: 1947-05-11T01:00:00+0000 +-710380800: 1947-06-29T00:00:00+0000 +-701910000: 1947-10-05T01:00:00+0000 +-684975600: 1948-04-18T01:00:00+0000 +-670460400: 1948-10-03T01:00:00+0000 +-654130800: 1949-04-10T01:00:00+0000 +-639010800: 1949-10-02T01:00:00+0000 +315529200: 1979-12-31T23:00:00+0000 +323830800: 1980-04-06T01:00:00+0000 +338950800: 1980-09-28T01:00:00+0000 +354675600: 1981-03-29T01:00:00+0000 +370400400: 1981-09-27T01:00:00+0000 +386125200: 1982-03-28T01:00:00+0000 +401850000: 1982-09-26T01:00:00+0000 +417574800: 1983-03-27T01:00:00+0000 +433299600: 1983-09-25T01:00:00+0000 +449024400: 1984-03-25T01:00:00+0000 +465354000: 1984-09-30T01:00:00+0000 +481078800: 1985-03-31T01:00:00+0000 +496803600: 1985-09-29T01:00:00+0000 +512528400: 1986-03-30T01:00:00+0000 +528253200: 1986-09-28T01:00:00+0000 +543978000: 1987-03-29T01:00:00+0000 +559702800: 1987-09-27T01:00:00+0000 +575427600: 1988-03-27T01:00:00+0000 +591152400: 1988-09-25T01:00:00+0000 +606877200: 1989-03-26T01:00:00+0000 +622602000: 1989-09-24T01:00:00+0000 +638326800: 1990-03-25T01:00:00+0000 +654656400: 1990-09-30T01:00:00+0000 +670381200: 1991-03-31T01:00:00+0000 +686106000: 1991-09-29T01:00:00+0000 +701830800: 1992-03-29T01:00:00+0000 +717555600: 1992-09-27T01:00:00+0000 +733280400: 1993-03-28T01:00:00+0000 +749005200: 1993-09-26T01:00:00+0000 +764730000: 1994-03-27T01:00:00+0000 +780454800: 1994-09-25T01:00:00+0000 +796179600: 1995-03-26T01:00:00+0000 +811904400: 1995-09-24T01:00:00+0000 +828234000: 1996-03-31T01:00:00+0000 +846378000: 1996-10-27T01:00:00+0000 +859683600: 1997-03-30T01:00:00+0000 +877827600: 1997-10-26T01:00:00+0000 +891133200: 1998-03-29T01:00:00+0000 +909277200: 1998-10-25T01:00:00+0000 +922582800: 1999-03-28T01:00:00+0000 +941331600: 1999-10-31T01:00:00+0000 +954032400: 2000-03-26T01:00:00+0000 +972781200: 2000-10-29T01:00:00+0000 +985482000: 2001-03-25T01:00:00+0000 +1004230800: 2001-10-28T01:00:00+0000 +1017536400: 2002-03-31T01:00:00+0000 +1035680400: 2002-10-27T01:00:00+0000 +1048986000: 2003-03-30T01:00:00+0000 +1067130000: 2003-10-26T01:00:00+0000 +1080435600: 2004-03-28T01:00:00+0000 +1099184400: 2004-10-31T01:00:00+0000 +1111885200: 2005-03-27T01:00:00+0000 +1130634000: 2005-10-30T01:00:00+0000 +1143334800: 2006-03-26T01:00:00+0000 +1162083600: 2006-10-29T01:00:00+0000 +1174784400: 2007-03-25T01:00:00+0000 +1193533200: 2007-10-28T01:00:00+0000 +1206838800: 2008-03-30T01:00:00+0000 +1224982800: 2008-10-26T01:00:00+0000 +1238288400: 2009-03-29T01:00:00+0000 +1256432400: 2009-10-25T01:00:00+0000 +1269738000: 2010-03-28T01:00:00+0000 +1288486800: 2010-10-31T01:00:00+0000 +1301187600: 2011-03-27T01:00:00+0000 +1319936400: 2011-10-30T01:00:00+0000 +1332637200: 2012-03-25T01:00:00+0000 +1351386000: 2012-10-28T01:00:00+0000 +1364691600: 2013-03-31T01:00:00+0000 +1382835600: 2013-10-27T01:00:00+0000 +1396141200: 2014-03-30T01:00:00+0000 +1414285200: 2014-10-26T01:00:00+0000 +1427590800: 2015-03-29T01:00:00+0000 +1445734800: 2015-10-25T01:00:00+0000 +1459040400: 2016-03-27T01:00:00+0000 +1477789200: 2016-10-30T01:00:00+0000 +1490490000: 2017-03-26T01:00:00+0000 +1509238800: 2017-10-29T01:00:00+0000 +1521939600: 2018-03-25T01:00:00+0000 +1540688400: 2018-10-28T01:00:00+0000 +1553994000: 2019-03-31T01:00:00+0000 +1572138000: 2019-10-27T01:00:00+0000 +1585443600: 2020-03-29T01:00:00+0000 +1603587600: 2020-10-25T01:00:00+0000 +1616893200: 2021-03-28T01:00:00+0000 +1635642000: 2021-10-31T01:00:00+0000 +1648342800: 2022-03-27T01:00:00+0000 +1667091600: 2022-10-30T01:00:00+0000 +1679792400: 2023-03-26T01:00:00+0000 +1698541200: 2023-10-29T01:00:00+0000 +1711846800: 2024-03-31T01:00:00+0000 +1729990800: 2024-10-27T01:00:00+0000 +1743296400: 2025-03-30T01:00:00+0000 +1761440400: 2025-10-26T01:00:00+0000 +1774746000: 2026-03-29T01:00:00+0000 +1792890000: 2026-10-25T01:00:00+0000 +1806195600: 2027-03-28T01:00:00+0000 +1824944400: 2027-10-31T01:00:00+0000 +1837645200: 2028-03-26T01:00:00+0000 +1856394000: 2028-10-29T01:00:00+0000 +1869094800: 2029-03-25T01:00:00+0000 +1887843600: 2029-10-28T01:00:00+0000 +1901149200: 2030-03-31T01:00:00+0000 +1919293200: 2030-10-27T01:00:00+0000 +1932598800: 2031-03-30T01:00:00+0000 +1950742800: 2031-10-26T01:00:00+0000 +1964048400: 2032-03-28T01:00:00+0000 +1982797200: 2032-10-31T01:00:00+0000 +1995498000: 2033-03-27T01:00:00+0000 +2014246800: 2033-10-30T01:00:00+0000 +2026947600: 2034-03-26T01:00:00+0000 +2045696400: 2034-10-29T01:00:00+0000 +2058397200: 2035-03-25T01:00:00+0000 +2077146000: 2035-10-28T01:00:00+0000 +2090451600: 2036-03-30T01:00:00+0000 +2108595600: 2036-10-26T01:00:00+0000 +2121901200: 2037-03-29T01:00:00+0000 +2140045200: 2037-10-25T01:00:00+0000 +0: 1970-01-01T00:00:00+0000 +315529200: 1979-12-31T23:00:00+0000 +323830800: 1980-04-06T01:00:00+0000 +338950800: 1980-09-28T01:00:00+0000 +354675600: 1981-03-29T01:00:00+0000 +370400400: 1981-09-27T01:00:00+0000 +386125200: 1982-03-28T01:00:00+0000 +401850000: 1982-09-26T01:00:00+0000 +417574800: 1983-03-27T01:00:00+0000 +433299600: 1983-09-25T01:00:00+0000 +449024400: 1984-03-25T01:00:00+0000 +465354000: 1984-09-30T01:00:00+0000 +481078800: 1985-03-31T01:00:00+0000 +496803600: 1985-09-29T01:00:00+0000 +512528400: 1986-03-30T01:00:00+0000 +528253200: 1986-09-28T01:00:00+0000 +543978000: 1987-03-29T01:00:00+0000 +559702800: 1987-09-27T01:00:00+0000 +575427600: 1988-03-27T01:00:00+0000 +591152400: 1988-09-25T01:00:00+0000 +606877200: 1989-03-26T01:00:00+0000 +622602000: 1989-09-24T01:00:00+0000 +638326800: 1990-03-25T01:00:00+0000 +654656400: 1990-09-30T01:00:00+0000 +670381200: 1991-03-31T01:00:00+0000 +686106000: 1991-09-29T01:00:00+0000 +701830800: 1992-03-29T01:00:00+0000 +717555600: 1992-09-27T01:00:00+0000 +733280400: 1993-03-28T01:00:00+0000 +749005200: 1993-09-26T01:00:00+0000 +764730000: 1994-03-27T01:00:00+0000 +780454800: 1994-09-25T01:00:00+0000 +796179600: 1995-03-26T01:00:00+0000 +811904400: 1995-09-24T01:00:00+0000 +828234000: 1996-03-31T01:00:00+0000 +846378000: 1996-10-27T01:00:00+0000 +859683600: 1997-03-30T01:00:00+0000 +877827600: 1997-10-26T01:00:00+0000 +891133200: 1998-03-29T01:00:00+0000 +909277200: 1998-10-25T01:00:00+0000 +922582800: 1999-03-28T01:00:00+0000 +941331600: 1999-10-31T01:00:00+0000 +954032400: 2000-03-26T01:00:00+0000 +972781200: 2000-10-29T01:00:00+0000 +985482000: 2001-03-25T01:00:00+0000 +1004230800: 2001-10-28T01:00:00+0000 +1017536400: 2002-03-31T01:00:00+0000 +1035680400: 2002-10-27T01:00:00+0000 +1048986000: 2003-03-30T01:00:00+0000 +1067130000: 2003-10-26T01:00:00+0000 +1080435600: 2004-03-28T01:00:00+0000 +1099184400: 2004-10-31T01:00:00+0000 +1111885200: 2005-03-27T01:00:00+0000 +1130634000: 2005-10-30T01:00:00+0000 +1143334800: 2006-03-26T01:00:00+0000 +1162083600: 2006-10-29T01:00:00+0000 +1174784400: 2007-03-25T01:00:00+0000 +1193533200: 2007-10-28T01:00:00+0000 +1206838800: 2008-03-30T01:00:00+0000 +1224982800: 2008-10-26T01:00:00+0000 +1238288400: 2009-03-29T01:00:00+0000 +1256432400: 2009-10-25T01:00:00+0000 +1269738000: 2010-03-28T01:00:00+0000 +1288486800: 2010-10-31T01:00:00+0000 +1301187600: 2011-03-27T01:00:00+0000 +1319936400: 2011-10-30T01:00:00+0000 +1332637200: 2012-03-25T01:00:00+0000 +1351386000: 2012-10-28T01:00:00+0000 +1364691600: 2013-03-31T01:00:00+0000 +1382835600: 2013-10-27T01:00:00+0000 +1396141200: 2014-03-30T01:00:00+0000 +1414285200: 2014-10-26T01:00:00+0000 +1427590800: 2015-03-29T01:00:00+0000 +1445734800: 2015-10-25T01:00:00+0000 +1459040400: 2016-03-27T01:00:00+0000 +1477789200: 2016-10-30T01:00:00+0000 +1490490000: 2017-03-26T01:00:00+0000 +1509238800: 2017-10-29T01:00:00+0000 +1521939600: 2018-03-25T01:00:00+0000 +1540688400: 2018-10-28T01:00:00+0000 +1553994000: 2019-03-31T01:00:00+0000 +1572138000: 2019-10-27T01:00:00+0000 +1585443600: 2020-03-29T01:00:00+0000 +1603587600: 2020-10-25T01:00:00+0000 +1616893200: 2021-03-28T01:00:00+0000 +1635642000: 2021-10-31T01:00:00+0000 +1648342800: 2022-03-27T01:00:00+0000 +1667091600: 2022-10-30T01:00:00+0000 +1679792400: 2023-03-26T01:00:00+0000 +1698541200: 2023-10-29T01:00:00+0000 +1711846800: 2024-03-31T01:00:00+0000 +1729990800: 2024-10-27T01:00:00+0000 +1743296400: 2025-03-30T01:00:00+0000 +1761440400: 2025-10-26T01:00:00+0000 +1774746000: 2026-03-29T01:00:00+0000 +1792890000: 2026-10-25T01:00:00+0000 +1806195600: 2027-03-28T01:00:00+0000 +1824944400: 2027-10-31T01:00:00+0000 +1837645200: 2028-03-26T01:00:00+0000 +1856394000: 2028-10-29T01:00:00+0000 +1869094800: 2029-03-25T01:00:00+0000 +1887843600: 2029-10-28T01:00:00+0000 +1901149200: 2030-03-31T01:00:00+0000 +1919293200: 2030-10-27T01:00:00+0000 +1932598800: 2031-03-30T01:00:00+0000 +1950742800: 2031-10-26T01:00:00+0000 +1964048400: 2032-03-28T01:00:00+0000 +1982797200: 2032-10-31T01:00:00+0000 +1995498000: 2033-03-27T01:00:00+0000 +2014246800: 2033-10-30T01:00:00+0000 +2026947600: 2034-03-26T01:00:00+0000 +2045696400: 2034-10-29T01:00:00+0000 +2058397200: 2035-03-25T01:00:00+0000 +2077146000: 2035-10-28T01:00:00+0000 +2090451600: 2036-03-30T01:00:00+0000 +2108595600: 2036-10-26T01:00:00+0000 +2121901200: 2037-03-29T01:00:00+0000 +2140045200: 2037-10-25T01:00:00+0000 +9223372036854775807: 292277026596-12-04T15:30:07+0000 +==DONE==