Zeller’s Congruence

October 8, 2010

Zeller’s Congruence is a simple mathematical method for determining the day of the week for a given date.

In the 1880s, Christian Zeller, a German mathematician, noticed that, if you run a year from March through February, the cumulative number of days in each month forms a nearly straight line; that works because February, which would normally perturb the straight line, is moved to the end. He worked out the formula ⌊(13m−1)/5⌋ to give the number of weekdays that the start of the month moves each month, where m is the month number.

Then it is easy to calculate the day of the week for any given day: add the day of the month, the offset for the number of months since March, an offset for each year, and additional offsets for leap years and leap centuries (remembering to subtract one year for dates in January and February), taking the whole thing mod 7. It’s fun to work out the arithmetic yourself, but if you don’t want to take the time, the whole formula is shown in the solution.

Your task is to write a function that uses Zeller’s Congruence to calculate the day of the week for any given date. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Advertisement

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 )

Connecting to %s

%d bloggers like this: