mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-13 11:42:38 +03:00
LibC: Make localtime() and gmtime() handle years before 1970
Year computation has to be based on seconds, not days, in case t is < 0 but t / __seconds_per_day is 0. Year computation also has to consider negative timestamps. With this, days is always positive and <= the number of days in the year, so base the tm_wday computation directly on the timestamp, and do it first, before t is modified in the year computation. In C, % can return a negative number if the left operand is negative, compensate for that. Tested via test-js. (Except for tm_wday, since we don't implement Date.prototype.getUTCDate() yet.)
This commit is contained in:
parent
fc28c9b085
commit
5f595e7e1b
Notes:
sideshowbarker
2024-07-19 03:16:10 +09:00
Author: https://github.com/nico Commit: https://github.com/SerenityOS/serenity/commit/5f595e7e1b1 Pull-request: https://github.com/SerenityOS/serenity/pull/3269
@ -69,16 +69,24 @@ static const int __seconds_per_day = 60 * 60 * 24;
|
||||
|
||||
static void time_to_tm(struct tm* tm, time_t t)
|
||||
{
|
||||
tm->tm_wday = (4 * __seconds_per_day + t) % (7 * __seconds_per_day); // 1970-01-01 was a Thursday.
|
||||
if (tm->tm_wday < 0)
|
||||
tm->tm_wday += 7 * __seconds_per_day;
|
||||
tm->tm_wday /= __seconds_per_day;
|
||||
|
||||
int year = 1970;
|
||||
for (; t >= (365 + __is_leap_year(year)) * __seconds_per_day; ++year)
|
||||
t -= (365 + __is_leap_year(year)) * __seconds_per_day;
|
||||
for (; t < 0; --year)
|
||||
t += (365 + __is_leap_year(year - 1)) * __seconds_per_day;
|
||||
ASSERT(t >= 0);
|
||||
|
||||
int days = t / __seconds_per_day;
|
||||
int remaining = t % __seconds_per_day;
|
||||
tm->tm_sec = remaining % 60;
|
||||
remaining /= 60;
|
||||
tm->tm_min = remaining % 60;
|
||||
tm->tm_hour = remaining / 60;
|
||||
tm->tm_wday = (4 + days) % 7;
|
||||
int year;
|
||||
for (year = 1970; days >= 365 + __is_leap_year(year); ++year)
|
||||
days -= 365 + __is_leap_year(year);
|
||||
tm->tm_year = year - 1900;
|
||||
tm->tm_yday = days;
|
||||
tm->tm_mday = 1;
|
||||
|
@ -1,9 +1,7 @@
|
||||
test("basic functionality", () => {
|
||||
expect(new Date(1597955034555).toISOString()).toBe("2020-08-20T20:23:54.555Z");
|
||||
|
||||
// FIXME: Add these once they work.
|
||||
//expect(new Date(Date.UTC(22020)).toISOString()).toBe("+022020-01-01T00:00:00.000Z");
|
||||
//expect(new Date(Date.UTC(1950)).toISOString()).toBe("1950-01-01T00:00:00.000Z");
|
||||
//expect(new Date(Date.UTC(1800)).toISOString()).toBe("1800-01-01T00:00:00.000Z");
|
||||
//expect(new Date(Date.UTC(-100)).toISOString()).toBe("-000100-01-01T00:00:00.000Z");
|
||||
expect(new Date(Date.UTC(22020)).toISOString()).toBe("+022020-01-01T00:00:00.000Z");
|
||||
expect(new Date(Date.UTC(1950)).toISOString()).toBe("1950-01-01T00:00:00.000Z");
|
||||
expect(new Date(Date.UTC(1800)).toISOString()).toBe("1800-01-01T00:00:00.000Z");
|
||||
expect(new Date(Date.UTC(-100)).toISOString()).toBe("-000100-01-01T00:00:00.000Z");
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user