Zeller’s algorithm in Python
Posted by Samath
Last Updated: March 12, 2015

Zeller's congruence is an algorithm devised by Christian Zeller to compute the day of the week on which
a given date will fall (or fell). In this exercise, you will write some code to implement Zeller’s algorithm
and use that code to answer a question or two. Your code should use the algorithm outlined below,
Let A, B, C, D denote integer variables that have the following values:

- A = the month of the year, with March having the value 1, April the value 2, . . ., December the
value 10, and January and February being counted as months 11 and 12 of the preceding year
- B = the day of the month (1, 2, 3, . . . , 30, 31)
- C = the year of the century (e.g. C = 89 for the year 1989)
- D = the century (e.g. D = 19 for the year 1989)

Note: if the month is January or February, then the preceding year is used for computation. This is
because there was a period in history when March 1st, not January 1st, was the beginning of the year.
Let W, X, Y, Z, R also denote integer variables. Compute their values in the following order using
integer arithmetic:

- W = (13*A - 1) / 5
- X = C / 4
- Y = D / 4
- Z = W + X + Y + B + C - 2*D
- R = the remainder when Z is divided by 7

The value of R is the day of the week, where 0 represents Sunday, 1 is Monday, 2, is Tuesday, ... , 6 is
Saturday.

1. Write a function called z eller that accepts three(3) arguments: day, month and year. z eller
returns the day of the week that that date fell on as a string. For example,
>>> zeller(1,1,2015)
‘Thursday’
>>>

Test your function with many different dates in the past (recent and distant), future, and today.

2. Modify zeller to return its result as an integer in the range 0 to 6, inclusive. For example,
>>> zeller(1,1,2015)
4
>>>

3. Now write a function called howMany . This function returns a count of the number of occasions
when a given day and month fell on a given weekday within a given period of time. h owMany
accepts five (5) integer arguments:

a. weekday is an integer in the range 0-6 and represents a day of the week
b. day represents a day of a month and can range between 1 and 31
c. month represents a month of a year and can range between 1 and 12
d. start represents the first year of the period being considered
e. end represents the year after the last of the period being considered

For example, if we wanted to know on how many occasions January 1st fell on a Sunday during
the 20th century (Jan 1901 to Dec 2000), we would call howMany with the following
arguments,
>>> howMany(0,1,1,1901,2000)
14
>>>
howMany calls on the services of zeller written in step 2. W rite this function using a f or
loop .

4. Write a function called o ccurences. This function states the weekday that that day and month
fell most and least frequently on. The function accepts four (4) integer arguments:
a. day represents a day of a month and can range between 1 and 31
b. month represents a month of a year and can range between 1 and 12
c. start represents the first year of the period being considered
d. end represents the year after the last of the period being considered

For example, if we wanted to know the weekdays that January 1st fell most and least frequently
on during the 20th century (Jan 1901 to Dec 2000), we would call o ccurences with the following arguments,
>>> occurences(1,1,1901,2000)
That date falls most often on a Wednesday and least often on a
Saturday within the given period
>>>

5. Take a look at h owMany and o ccurences, in particular their parameter lists. Their parameter
lists are exactly the same with one exception, the w eekday parameter of h owMany. This
suggests that we could rewrite h owMany as a function local to o ccurences. Rewrite the two
functions with h owMany local to o ccurences. Remember the scope of your parameters and
variables. Your rewritten h owMany function must now accept only one (1) parameter,
weekday, but the rest of its functionality must remain exactly the same. o ccurences will also
provide the same functionality as it previously did. For example,

>>> occurences(29,2,1901,2000)
That date falls most often on a Monday and least often on a
Tuesday within the given period
>>>

6. Finally, recall that whatever we write iteratively, we can rewrite recursively (and vice versa). In step 3 we wrote h owMany iteratively using a f or loop, and then rewrote it as a function local to o ccurences. Now, rewrite the version of h owMany you wrote in step 5 above i.e. as a local function that accepts one parameter, as a function with a locally defined, recursive, helper function i.e. the recursive helper function (call it c ount) must itself be defined within h owMany. Remember to test o ccurences after rewriting h owMany with its local recursive function count , to ensure it still works as it should.

Code:

#Question 1
def zeller(day, month, year):
        
    if(month == 1):
        A = 11
        myy = year-1
    elif(month == 2):
        A = 12
        myy = year-1
    elif(month == 3):
        A = 1
        myy = year
    elif(month == 4):
        A = 2
        myy = year
    elif(month == 5):
        A = 3
        myy = year
    elif(month == 6):
        A = 4
        myy = year
    elif(month == 7):
        A = 5
        myy = year
    elif(month == 8):
        A = 6
        myy = year
    elif(month == 9):
        A = 7
        myy = year
    elif(month == 10):
        A = 8
        myy = year
    elif(month == 11):
        A = 9
        myy = year
    elif(month == 12):
        A = 10
        myy = year

    yOcList = list(str(myy))
    yearOfCentury = yOcList[2]+yOcList[3]

    CenturyList = list(str(myy))
    Century = yOcList[0]+yOcList[1]

    B = day
    C = int(yearOfCentury)
    D = int(Century)

    W = (13*int(A) -1)/5
    X = int(C)/4
    Y = int(D)/4
    Z = int(W) + int(X) + int(Y) + int(B) + int(C) - 2*int(D)
    R = int(Z)%7
    

    if(int(R)==0):
        return "Sunday"
    elif(int(R)==1):
        return "Monday"
    elif(int(R)==2):
        return "Tuesday"
    elif(int(R)==3):
        return "Wednesday"
    elif(int(R)==4):
        return "Thursday"
    elif(int(R)==5):
        return "Friday"
    elif(int(R)==6):
        return "Saturday"

#Question 2
    
def zeller(day, month, year):
        
    if(month == 1):
        A = 11
        myy = year-1
    elif(month == 2):
        A = 12
        myy = year-1
    elif(month == 3):
        A = 1
        myy = year
    elif(month == 4):
        A = 2
        myy = year
    elif(month == 5):
        A = 3
        myy = year
    elif(month == 6):
        A = 4
        myy = year
    elif(month == 7):
        A = 5
        myy = year
    elif(month == 8):
        A = 6
        myy = year
    elif(month == 9):
        A = 7
        myy = year
    elif(month == 10):
        A = 8
        myy = year
    elif(month == 11):
        A = 9
        myy = year
    elif(month == 12):
        A = 10
        myy = year

    yOcList = list(str(myy))
    yearOfCentury = yOcList[2]+yOcList[3]


    CenturyList = list(str(myy))
    Century = yOcList[0]+yOcList[1]

    B = day
    C = int(yearOfCentury)
    D = int(Century)

    W = (13*int(A) -1)/5
    X = int(C)/4
    Y = int(D)/4
    Z = int(W) + int(X) + int(Y) + int(B) + int(C) - 2*int(D)
    R = int(Z)%7
    
    return int(R)

#Question 3

def howMany(weekday,day, month, start, end):
    ans = 0
    for i in range(start,end):
        wd = zeller(day, month, i)
        if(weekday == wd):
            ans+=1
    return ans

#Question 4

def occurences(day,month,start,end): 
    max_check=max([howMany(1,day, month, start, end),howMany(2,day, month, start, end),howMany(3,day, month, start, end),howMany(4,day, month, start, end),howMany(5,day, month, start, end),howMany(6,day, month, start, end),howMany(0,day, month, start, end)])
    if (max_check==howMany(0,day, month, start, end)):
        occurMost="Sunday"
    elif(max_check==howMany(1,day, month, start, end)):
        occurMost="Monday"
    elif(max_check==howMany(2,day, month, start, end)):
        occurMost="Tuesday"
    elif(max_check==howMany(3,day, month, start, end)):
        occurMost="Wednesday"
    elif(max_check==howMany(4,day, month, start, end)):
        occurMost="Thursday"
    elif(max_check==howMany(5,day, month, start, end)):
        occurMost="Friday"
    elif(max_check==howMany(6,day, month, start, end)):
        occurMost="Saturday"

    min_check=min([howMany(1,day, month, start, end),howMany(2,day, month, start, end),howMany(3,day, month, start, end),howMany(4,day, month, start, end),howMany(5,day, month, start, end),howMany(6,day, month, start, end),howMany(0,day, month, start, end)])
    if (min_check==howMany(0,day, month, start, end)):
        occurLeast="Sunday"
    elif(min_check==howMany(1,day, month, start, end)):
        occurLeast="Monday"
    elif(min_check==howMany(2,day, month, start, end)):
        occurLeast="Tuesday"
    elif(min_check==howMany(3,day, month, start, end)):
        occurLeast="Wednesday"
    elif(min_check==howMany(4,day, month, start, end)):
        occurLeast="Thursday"
    elif(min_check==howMany(5,day, month, start, end)):
        occurLeast="Friday"
    elif(min_check==howMany(6,day, month, start, end)):
        occurLeast="Saturday"

    return "That date falls most often on a " +occurMost+" and least often on a "+occurLeast+" within the given period"        

#Question 5

def occurences(day,month,start,end):
    def howMany(weekday):
        ans = 0
        for i in range(start,end):
            wd = zeller(day, month, i)
            if(weekday == wd):
                ans+=1
        return ans
        
    max_check=max([howMany(1),howMany(2),howMany(3),howMany(4),howMany(5),howMany(6),howMany(0)])
    if (max_check==howMany(0)):
        occurMost="Sunday"
    elif(max_check==howMany(1)):
        occurMost="Monday"
    elif(max_check==howMany(2)):
        occurMost="Tuesday"
    elif(max_check==howMany(3)):
        occurMost="Wednesday"
    elif(max_check==howMany(4)):
        occurMost="Thursday"
    elif(max_check==howMany(5)):
        occurMost="Friday"
    elif(max_check==howMany(6)):
        occurMost="Saturday"

    min_check=min([howMany(1),howMany(2),howMany(3),howMany(4),howMany(5),howMany(6),howMany(0)])
    if (min_check==howMany(0)):
        occurLeast="Sunday"
    elif(min_check==howMany(1)):
        occurLeast="Monday"
    elif(min_check==howMany(2)):
        occurLeast="Tuesday"
    elif(min_check==howMany(3)):
        occurLeast="Wednesday"
    elif(min_check==howMany(4)):
        occurLeast="Thursday"
    elif(min_check==howMany(5)):
        occurLeast="Friday"
    elif(min_check==howMany(6)):
        occurLeast="Saturday"

    return "That date falls most often on a " +occurMost+" and least often on a "+occurLeast+" within the given period"




#Question 6
      
def occurences(day,month,start,end):
    def howMany(weekday):
        def count(start,end):
            wd = zeller(day, month, start)                               
            if(start >= end):
                return 0
            else:
                if(weekday == wd):
                    return count(start+1,end) + 1
                else:
                    return count(start+1,end)
        return count(start,end)
        
    max_check=max([howMany(1),howMany(2),howMany(3),howMany(4),howMany(5),howMany(6),howMany(0)])
    if (max_check==howMany(0)):
        occurMost="Sunday"
    elif(max_check==howMany(1)):
        occurMost="Monday"
    elif(max_check==howMany(2)):
        occurMost="Tuesday"
    elif(max_check==howMany(3)):
        occurMost="Wednesday"
    elif(max_check==howMany(4)):
        occurMost="Thursday"
    elif(max_check==howMany(5)):
        occurMost="Friday"
    elif(max_check==howMany(6)):
        occurMost="Saturday"

    min_check=min([howMany(1),howMany(2),howMany(3),howMany(4),howMany(5),howMany(6),howMany(0)])
    if (min_check==howMany(0)):
        occurLeast="Sunday"
    elif(min_check==howMany(1)):
        occurLeast="Monday"
    elif(min_check==howMany(2)):
        occurLeast="Tuesday"
    elif(min_check==howMany(3)):
        occurLeast="Wednesday"
    elif(min_check==howMany(4)):
        occurLeast="Thursday"
    elif(min_check==howMany(5)):
        occurLeast="Friday"
    elif(min_check==howMany(6)):
        occurLeast="Saturday"

    return "That date falls most often on a " +occurMost+" and least often on a "+occurLeast+" within the given period"