#!/usr/bin/python
import datetime
import math
"""From ITS src/libdoc/time.kmp8
;;; The following function, when given the date as three numbers,
;;; will produce a number of the day-of-week for that date (0=Monday).
DAY-OF-THE-WEEK-STRING treats 0 as Monday.
"""
"""
Python // and MACLISP // round differently for negative numbers:
>>> 8//3
2
>>> 8//-3
-3
>>> -8//3
-3
("the result is that of mathematical division with the 'floor' function applied
to the result")
(// 8 3)
2
(// 8 -3)
-2
(// -8 3)
-2
(So this looks like division followed by round-towards-zero.)
"""
def mldiv(a, b):
return math.trunc(float(a) / b)
"""
Python % and MACLISP \ also differ:
>>> 8%3
2
>>> 8%-3
-1
>>> -8%3
1
("The modulo operator always yields a result with the same sign as its second
operand (or zero); the absolute value of the result is strictly smaller than
the absolute value of the second operand")
(\ 8 3)
2
(\ 8 -3)
2
(\ -8 3)
-2
(Same sign as first operand.)
But this doesn't matter because we're only using \ with positive operands
below...
"""
def day_of_week(day, month, year):
#(DEFUN TIME:ON-WHAT-DAY-OF-THE-WEEK? (DAY MONTH YEAR)
# (IF (NOT (AND (FIXP YEAR) (FIXP MONTH) (FIXP DAY)))
# (ERROR "Args to TIME:DAY-OF-WEEK must be fixnums" (LIST YEAR MONTH DAY))
# (SETQ YEAR (STANDARDIZE-YEAR YEAR))
# (LET ((A (+ YEAR (// (+ MONTH -14.) 12.))))
a = year + mldiv((month - 14), 12)
# [So this is based on when March starts...]
# (DECLARE (FIXNUM A))
# (\ (+ (// (1- (* 13. (+ MONTH 10. (* (// (+ MONTH 10.) -13.) 12.))))
# 5.)
return (mldiv(13 * (month + 10 + ((mldiv(month + 10, -13) * 12))) - 1, 5)
# DAY
+ day
# 76.
+ 76
# (// (* 5. (- A (* (// A 100.) 100.))) 4.)
+ mldiv((5 * (a - (mldiv(a, 100) * 100))), 4)
# (// A -2000.)
# + mldiv(a, -2000) - removing this fixes it!
# (// A 400.)
+ mldiv(a, 400)
# (* (// A -100.) 2.))
# 7.))))
+ (mldiv(a, -100) * 2)) % 7
days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
#;;; eg,
#;;; (TIME:DAY-OF-THE-WEEK-STRING
#;;; (TIME:ON-WHAT-DAY-OF-THE-WEEK? 22. 11. 1963.))
#;;; => "Friday"
#;;; which happened to be the day President John F. Kennedy was assasinated.
assert days[day_of_week(22, 11, 1963)] == "Fri"
for y in range(1753, 10000):
for m in range(1, 13):
for d in range(1, 29): # XXX check 29/30 too
dt = datetime.date(y, m, d)
pyday = dt.isoweekday() - 1
itsday = day_of_week(d, m, y)
if pyday != itsday:
print "%04d-%02d-%02d py=%s its=%s" % (y, m, d, days[pyday], days[itsday])