From 1c9581f383d947d35d19f7266839fef401b981cb Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Mon, 24 Aug 2020 09:19:50 -0400 Subject: [PATCH] LibC: Make mktime() / gmtime() more POSIX-compliant mktime() is supposed to fill in tm_wday and tm_yday, and it it's supposed to canonicalize out-of-range values (that is, "Jan 31" is turned into "Feb 1"). Instead of making the straightfoward tm_to_time() implementation more complicated, just make it call time_to_tm() once the timestamp is computed to break it back down ot (canonical) tm entries. --- Libraries/LibC/time.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Libraries/LibC/time.cpp b/Libraries/LibC/time.cpp index 018ccf6cdac..68810ae5096 100644 --- a/Libraries/LibC/time.cpp +++ b/Libraries/LibC/time.cpp @@ -103,6 +103,16 @@ static void time_to_tm(struct tm* tm, time_t t) static time_t tm_to_time(struct tm* tm, long timezone_adjust_seconds) { + // "The original values of the tm_wday and tm_yday components of the structure are ignored, + // and the original values of the other components are not restricted to the ranges described in . + // [...] + // Upon successful completion, the values of the tm_wday and tm_yday components of the structure shall be set appropriately, + // and the other components are set to represent the specified time since the Epoch, + // but with their values forced to the ranges indicated in the entry; + // the final value of tm_mday shall not be set until tm_mon and tm_year are determined." + + // FIXME: Handle tm_isdst eventually. + tm->tm_year += tm->tm_mon / 12; tm->tm_mon %= 12; if (tm->tm_mon < 0) { @@ -125,7 +135,9 @@ static time_t tm_to_time(struct tm* tm, long timezone_adjust_seconds) days += tm->tm_yday; int seconds = tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; - return static_cast(days) * __seconds_per_day + seconds + timezone_adjust_seconds; + auto timestamp = static_cast(days) * __seconds_per_day + seconds + timezone_adjust_seconds; + time_to_tm(tm, timestamp); + return timestamp; } time_t mktime(struct tm* tm)