## 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:

$f = k + \lfloor (13 m - 1)/5 \rfloor + d + \lfloor \frac{d}{4} \rfloor + \lfloor \frac{c}{4} \rfloor - 2 c \mod 7$

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.

Pages: 1 2

### 5 Responses to “Zeller’s Congruence”

1. […] today’s Programming Praxis exercise, our goal is to implement a function created by Christian Zeller to […]

2. Remco Niemeijer said

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 100

3. slabounty said
# 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)


4. Khanh Nguyen said
open System
open System.Collections.Generic
open Microsoft.FSharp.Collections
open Microsoft.FSharp.Math

(*
*)
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 10

5. […] 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 […]