diff --git a/AK/Time.cpp b/AK/Time.cpp index ea9e470dba..b8db7db208 100644 --- a/AK/Time.cpp +++ b/AK/Time.cpp @@ -51,4 +51,14 @@ int days_in_month(int year, unsigned month) bool is_long_month = (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12); return is_long_month ? 31 : 30; } + +unsigned day_of_week(int year, unsigned month, int day) +{ + ASSERT(month >= 1 && month <= 12); + static const int seek_table[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; + if (month < 3) + --year; + + return (year + year / 4 - year / 100 + year / 400 + seek_table[month - 1] + day) % 7; +} } diff --git a/AK/Time.h b/AK/Time.h index f70b6f828d..e1475033d4 100644 --- a/AK/Time.h +++ b/AK/Time.h @@ -28,6 +28,12 @@ namespace AK { +// Month and day start at 1. Month must be >= 1 and <= 12. +// The return value is 0-indexed, that is 0 is Sunday, 1 is Monday, etc. +// Day may be negative or larger than the number of days +// in the given month. +unsigned day_of_week(int year, unsigned month, int day); + // Month and day start at 1. Month must be >= 1 and <= 12. // The return value is 0-indexed, that is Jan 1 is day 0. // Day may be negative or larger than the number of days @@ -176,6 +182,7 @@ inline bool operator!=(const TimespecType& a, const TimespecType& b) } +using AK::day_of_week; using AK::day_of_year; using AK::days_in_month; using AK::days_in_year; diff --git a/Libraries/LibC/time.cpp b/Libraries/LibC/time.cpp index 1cfb6da0b3..89e279ec60 100644 --- a/Libraries/LibC/time.cpp +++ b/Libraries/LibC/time.cpp @@ -64,11 +64,6 @@ 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 >= days_in_year(year) * __seconds_per_day; ++year) t -= days_in_year(year) * __seconds_per_day; @@ -89,8 +84,9 @@ static void time_to_tm(struct tm* tm, time_t t) for (month = 1; month < 12 && days >= days_in_month(year, month); ++month) days -= days_in_month(year, month); - tm->tm_mon = month - 1; tm->tm_mday = days + 1; + tm->tm_wday = day_of_week(year, month, tm->tm_mday); + tm->tm_mon = month - 1; } static time_t tm_to_time(struct tm* tm, long timezone_adjust_seconds) diff --git a/Libraries/LibCore/DateTime.cpp b/Libraries/LibCore/DateTime.cpp index d632e321da..64c48a9075 100644 --- a/Libraries/LibCore/DateTime.cpp +++ b/Libraries/LibCore/DateTime.cpp @@ -61,12 +61,7 @@ DateTime DateTime::from_timestamp(time_t timestamp) unsigned DateTime::weekday() const { - int target_year = m_year; - static const int seek_table[] = { 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4 }; - if (m_month < 3) - --target_year; - - return (target_year + target_year / 4 - target_year / 100 + target_year / 400 + seek_table[m_month - 1] + m_day) % 7; + return ::day_of_week(m_year, m_month, m_day); } unsigned DateTime::days_in_month() const