October 8, 2010 9:00 AM
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.
Posted by programmingpraxis
Categories: Exercises
Tags:
Mobile Site | Full Site
Get a free blog at WordPress.com Theme: WordPress Mobile Edition by Alex King.
[…] today’s Programming Praxis exercise, our goal is to implement a function created by Christian Zeller to […]
By Programming Praxis – Zeller’s Congruence « Bonsai Code on October 8, 2010 at 12:11 PM
My Haskell solution (see http://bonsaicode.wordpress.com/2010/10/08/programming-praxis-zeller%E2%80%99s-congruence/ for a version with comments):
data Weekday = Su | Mo | Tu | We | Th | Fr | Sa deriving (Enum, Eq, Show) zeller :: Int -> Int -> Int -> Weekday zeller year month day = toEnum $ mod (day + div (13 * m - 1) 5 + d + div d 4 + div c 4 - 2 * c) 7 where y = if month < 3 then year - 1 else year m = if month < 3 then month + 10 else month - 2 (c, d) = divMod y 100By Remco Niemeijer on October 8, 2010 at 12:11 PM
# f = k + floor(13m - 1) / 5) + d + floor(d / 4) + floor(c / 4) - 2c mod 7 def zeller(year, month, day) months = %w[march april may june july august september october november december january february] weekdays = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday] k = day m = months.index(month.downcase) + 1 y = (m <= 10) ? year : year-1 d = y % 100 c = y / 100 f = (k + (((13*m) - 1) / 5).floor + d + (d/4).floor + (c/4).floor - (2*c)) % 7 weekdays[f] end puts zeller(2010, "october", 8)By slabounty on October 8, 2010 at 9:24 PM
open System open System.Collections.Generic open Microsoft.FSharp.Collections open Microsoft.FSharp.Math (* Follow http://en.wikipedia.org/wiki/Zeller%27s_congruence *) let zeller_congruence (year:int) (month:int) (day:int) = let weekdays = ["Saturday"; "Sunday"; "Monday"; "Tuesday"; "Wednesday"; "Thursday"; "Friday"] let m = float(if (month < 3) then month + 12 else month) let y = if (month < 3) then year - 1 else year let K = float(y % 100) let J = float(y / 100) let h = float(day) + floor ((m + 1.0)*26.0 / 10.0 ) + K + floor (K/4.0) + floor(J / 4.0) - 2.0*J weekdays.[int(h) % 7] zeller_congruence 2010 10 10 zeller_congruence 2010 2 10By Khanh Nguyen on October 10, 2010 at 5:14 PM
[…] 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 […]
By Thank God It’s Friday! « Programming Praxis on June 24, 2011 at 9:02 AM