Files

63 lines
1.9 KiB
Python

"""Day-of-week via Julian Day Number, handling Julian/Gregorian transition.
Dates before 1582-10-15 use the Julian calendar; on/after use Gregorian.
The gap 1582-10-05..14 did not exist, so those dates are invalid.
Month lengths (including leap-year February) are validated per calendar.
"""
def _julian_leap(y):
return y % 4 == 0
def _gregorian_leap(y):
return (y % 4 == 0 and y % 100 != 0) or (y % 400 == 0)
def _is_julian(y, m, d):
return (y, m, d) < (1582, 10, 15)
def _days_in_month(y, m, julian):
if m in (1, 3, 5, 7, 8, 10, 12):
return 31
if m in (4, 6, 9, 11):
return 30
leap = _julian_leap(y) if julian else _gregorian_leap(y)
return 29 if leap else 28
def _jdn_julian(y, m, d):
a = (14 - m) // 12
yy = y + 4800 - a
mm = m + 12 * a - 3
return d + (153 * mm + 2) // 5 + 365 * yy + yy // 4 - 32083
def _jdn_gregorian(y, m, d):
a = (14 - m) // 12
yy = y + 4800 - a
mm = m + 12 * a - 3
return d + (153 * mm + 2) // 5 + 365 * yy + yy // 4 - yy // 100 + yy // 400 - 32045
NAMES = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
def dow(y, m, d):
if not (1 <= m <= 12):
raise ValueError("invalid month")
julian = _is_julian(y, m, d)
# gap dates did not exist
if (1582, 10, 5) <= (y, m, d) <= (1582, 10, 14):
raise ValueError("date did not exist (Julian/Gregorian gap)")
if not (1 <= d <= _days_in_month(y, m, julian)):
raise ValueError("invalid day for month")
if julian:
jdn = _jdn_julian(y, m, d)
else:
jdn = _jdn_gregorian(y, m, d)
return NAMES[jdn % 7]
def main():
import sys
if len(sys.argv) != 4:
print("usage: zeller_dow.py YYYY MM DD"); return 2
y, m, d = int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3])
print(dow(y, m, d))
return 0
if __name__ == "__main__":
raise SystemExit(main())