Zeller’s Congruence
October 8, 2010
If you decided not to work out the formula yourself, Dr. Math gives an easy-to-read derivation. Here’s the formula:
Here k is the day of the month, m is the month number, taking March = 1 and February = 12, d is the last two digits of the year, and c is the first two digits of the year; when calculating the year number for d and c, the previous year is used during January and February. Then f is the day of the week, with Sunday = 0 and Saturday = 6.
Given the formula, it is easy to write a function to compute the day of the week:
(define (zeller year month day)
(let* ((m (if (< month 3) (+ month 10) (- month 2)))
(yr (if (< month 3) (- year 1) year))
(d (modulo yr 100)) (c (quotient yr 100)))
(list-ref '(Sunday Monday Tuesday Wednesday Thursday Friday Saturday)
(modulo (+ day (quotient (- (* 13 m) 1) 5) d
(quotient d 4) (quotient c 4) (* -2 c)) 7))))
We test the function using the julian and gregorian functions and the assert macro from the Standard Prelude; the test starts on January 1, 1753 and runs for a thousand years:
(do ((i 2361331 (+ i 1))) ((= i 2726573))
(let-values (((year month day) (gregorian i)))
(assert (list-ref '(Monday Tuesday Wednesday Thursday Friday Saturday Sunday)
(modulo (julian year month day) 7))
(zeller year month day))))
You can run the program at http://programmingpraxis.codepad.org/YNmQyDN1.
[…] today’s Programming Praxis exercise, our goal is to implement a function created by Christian Zeller to […]
My Haskell solution (see http://bonsaicode.wordpress.com/2010/10/08/programming-praxis-zeller%E2%80%99s-congruence/ for a version with comments):
[…] algorithms to calculate the day of the week, one in the Standard Prelude and one in the exercise on Zeller’s Congruence. In today’s exercise we give three more algorithms to calculate the day of the […]