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.

About these ads

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
    
    (*
    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 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 [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 621 other followers

%d bloggers like this: