Tim Wawrzynczak has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/31557
Change subject: rtc: Fix rtc_calc_weekday ......................................................................
rtc: Fix rtc_calc_weekday
This function appeared previously unused (called only from rtc_display, also unused), but it returned an incorrect weekday. Change the algorithm to use Zeller's Rule, a well-known algorithm for calculuating weekdays.
Change-Id: Ibce6822942f8d9d9f39c2b6065cd785dca9e8e09 Signed-off-by: Tim Wawrzynczak twawrzynczak@chromium.org --- M src/lib/rtc.c 1 file changed, 26 insertions(+), 43 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/57/31557/1
diff --git a/src/lib/rtc.c b/src/lib/rtc.c index c5c157f..1dd301c 100644 --- a/src/lib/rtc.c +++ b/src/lib/rtc.c @@ -27,51 +27,32 @@ #define DAYS_IN_YEAR(a) (LEAP_YEAR(a) ? 366 : 365) #define DAYS_IN_MONTH(a) (month_days[(a) - 1])
-static const int month_offset[] = { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 -}; - static const char *const weekdays[] = { "Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur", };
-static int leaps_to_year(int year) -{ - return year / 4 - year / 100 + year / 400; -} - -/* This only works for the Gregorian calendar after Jan 1 1971. */ +/* Zeller's rule */ static int rtc_calc_weekday(struct rtc_time *tm) { - int leaps_to_date; - int day; - if (tm->year < 1971) return -1;
- day = 4; /* Jan 1 1970 was a Thursday. */ - - /* Number of leap corrections to apply up to end of last year */ - leaps_to_date = leaps_to_year(tm->year - 1) - leaps_to_year(1970); - - /* - * This year is a leap year if it is divisible by 4 except when it is - * divisible by 100 unless it is divisible by 400 - * - * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 is. - */ - if ((tm->year % 4) && - ((tm->year % 100 != 0) || (tm->year % 400 == 0)) && - (tm->mon > 2)) { - /* We are past Feb. 29 in a leap year */ - day++; - } - - day += (tm->year - 1970) * 365 + leaps_to_date + - month_offset[tm->mon-1] + tm->mday; - tm->wday = day % 7; - - return 0; + /* k: Day of month */ + const int k = tm->mday; + /* m: Month number (March is 1, April 2, ... January 11, February 12) */ + const int m = (tm->mon < 3) ? tm->mon + 10 : tm->mon - 2; + /* D: Last 2 digits of year; but treat Jan/Feb as "last year" */ + const int D = ((tm->mon < 3) ? tm->year - 1 : tm->year) % 100; + /* C: First two digits of the year */ + const int C = tm->year / 100; + const int f = k + + (13 * m - 1) / 5 + + D + + (D >> 2) + + (C >> 2) + - 2 * C; + tm->wday = f % 7; + return 0; }
int rtc_to_tm(int tim, struct rtc_time *tm) @@ -139,16 +120,18 @@ }
days = (unsigned long)(year / 4 - year / 100 + year / 400 + - 367 * mon / 12 + tm->mday) + - year * 365 - 719499; + 367 * mon / 12 + tm->mday) + + year * 365 - 719499; hours = days * 24 + tm->hour; return (hours * 60 + tm->min) * 60 + tm->sec; }
-void rtc_display(const struct rtc_time *tm) +void rtc_display(struct rtc_time *tm) { - printk(BIOS_INFO, "Date: %4d-%02d-%02d (%sday) Time: %2d:%02d:%02d\n", - tm->year, tm->mon, tm->mday, - (tm->wday < 0 || tm->wday > 6) ? "unknown " : weekdays[tm->wday], - tm->hour, tm->min, tm->sec); + (void)rtc_calc_weekday(tm); + printk(BIOS_INFO, "Current Date: %4d-%02d-%02d (%sday) " + "Time: %2d:%02d:%02d\n", + tm->year, tm->mon, tm->mday, + (tm->wday < 0 || tm->wday > 6) ? "unknown " : weekdays[tm->wday], + tm->hour, tm->min, tm->sec); }