diff --git a/libc/src/time/mktime.cpp b/libc/src/time/mktime.cpp --- a/libc/src/time/mktime.cpp +++ b/libc/src/time/mktime.cpp @@ -11,7 +11,6 @@ namespace __llvm_libc { -namespace { constexpr int SecondsPerMin = 60; constexpr int MinutesPerHour = 60; constexpr int HoursPerDay = 24; @@ -27,26 +26,13 @@ // susceptible to the Year 2038 problem. constexpr int EndOf32BitEpochYear = 2038; -constexpr int LeapYearDaysInMonth[] = { - 31 /* Jan */, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -}; - constexpr int NonLeapYearDaysInMonth[] = { 31 /* Jan */, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -constexpr int LeapYearDaysByMonth[] = { - 0 /* Jan */, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 -}; - -constexpr int NonLeapYearDaysByMonth[] = { - 0 /* Jan */, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 -}; - constexpr bool isLeapYear (const time_t year) { return (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0)); } -} time_t LLVM_LIBC_ENTRYPOINT(mktime)(struct tm *t1) { // Unlike most C Library functions, mktime doesn't just die on bad input. @@ -79,22 +65,25 @@ } static_assert(sizeof(int) == 4, - "ILP64 is uimplemented. Ths implementation requires 32-bit " - "integers."); + "ILP64 is unimplemented. This implementation requires " + "32-bit integers."); if (t1->tm_mon < 0 || t1->tm_mon > (MonthsPerYear - 1)) return (time_t)(-1); bool tmYearIsLeap = isLeapYear(tmYearFromBase); - time_t daysInMonth = tmYearIsLeap - ? LeapYearDaysInMonth[t1->tm_mon] - : NonLeapYearDaysInMonth[t1->tm_mon]; + time_t daysInMonth = NonLeapYearDaysInMonth[t1->tm_mon]; + // Add one day if it is a leap year and the month is February. + if (tmYearIsLeap && t1->tm_mon == 1) + ++daysInMonth; if (t1->tm_mday < 1 || t1->tm_mday > daysInMonth) return (time_t)(-1); time_t totalDays = t1->tm_mday - 1; - totalDays += (tmYearIsLeap - ? LeapYearDaysByMonth[t1->tm_mon] - : NonLeapYearDaysByMonth[t1->tm_mon]); + for (int i = 0; i < t1->tm_mon; ++i) + totalDays += NonLeapYearDaysInMonth[i]; + // Add one day if it is a leap year and the month is after February. + if (tmYearIsLeap && t1->tm_mon > 1) + totalDays++; t1->tm_yday = totalDays; totalDays += (tmYearFromBase - EpochYear) * DaysPerNonLeapYear; @@ -111,7 +100,7 @@ t1->tm_wday = (EpochWeekDay + totalDays) % DaysPerWeek; if (t1->tm_wday < 0) t1->tm_wday += DaysPerWeek; - // TODO(rtenneti): Need to handle timezone + // TODO(rtenneti): Need to handle timezone and update of tm_isdst. return t1->tm_sec + t1->tm_min * SecondsPerMin + t1->tm_hour * MinutesPerHour * SecondsPerMin