|
| 1 | +#!/bin/python3 |
| 2 | +# Doomsday algorithm info: https://en.wikipedia.org/wiki/Doomsday_rule |
| 3 | + |
| 4 | +DOOMSDAY_LEAP = [4, 1, 7, 4, 2, 6, 4, 1, 5, 3, 7, 5] |
| 5 | +DOOMSDAY_NOT_LEAP = [3, 7, 7, 4, 2, 6, 4, 1, 5, 3, 7, 5] |
| 6 | +WEEK_DAY_NAMES = { |
| 7 | + 0: "Sunday", |
| 8 | + 1: "Monday", |
| 9 | + 2: "Tuesday", |
| 10 | + 3: "Wednesday", |
| 11 | + 4: "Thursday", |
| 12 | + 5: "Friday", |
| 13 | + 6: "Saturday", |
| 14 | +} |
| 15 | + |
| 16 | + |
| 17 | +def get_week_day(year: int, month: int, day: int) -> str: |
| 18 | + """Returns the week-day name out of a given date. |
| 19 | +
|
| 20 | + >>> get_week_day(2020, 10, 24) |
| 21 | + 'Saturday' |
| 22 | + >>> get_week_day(2017, 10, 24) |
| 23 | + 'Tuesday' |
| 24 | + >>> get_week_day(2019, 5, 3) |
| 25 | + 'Friday' |
| 26 | + >>> get_week_day(1970, 9, 16) |
| 27 | + 'Wednesday' |
| 28 | + >>> get_week_day(1870, 8, 13) |
| 29 | + 'Saturday' |
| 30 | + >>> get_week_day(2040, 3, 14) |
| 31 | + 'Wednesday' |
| 32 | +
|
| 33 | + """ |
| 34 | + # minimal input check: |
| 35 | + assert len(str(year)) > 2, "year should be in YYYY format" |
| 36 | + assert 1 <= month <= 12, "month should be between 1 to 12" |
| 37 | + assert 1 <= day <= 31, "day should be between 1 to 31" |
| 38 | + |
| 39 | + # Doomsday algorithm: |
| 40 | + century = year // 100 |
| 41 | + century_anchor = (5 * (century % 4) + 2) % 7 |
| 42 | + centurian = year % 100 |
| 43 | + centurian_m = centurian % 12 |
| 44 | + dooms_day = ( |
| 45 | + (centurian // 12) + centurian_m + (centurian_m // 4) + century_anchor |
| 46 | + ) % 7 |
| 47 | + day_anchor = ( |
| 48 | + DOOMSDAY_NOT_LEAP[month - 1] |
| 49 | + if (year % 4 != 0) or (centurian == 0 and (year % 400) == 0) |
| 50 | + else DOOMSDAY_LEAP[month - 1] |
| 51 | + ) |
| 52 | + week_day = (dooms_day + day - day_anchor) % 7 |
| 53 | + return WEEK_DAY_NAMES[week_day] |
| 54 | + |
| 55 | + |
| 56 | +if __name__ == "__main__": |
| 57 | + import doctest |
| 58 | + |
| 59 | + doctest.testmod() |
0 commit comments