Finding the Day of the Week - Zeller's Formula
Today's topic is not complicated, rather it is closely related to our daily lives.
0. What is Zeller's Formula?
Zeller's congruence is an algorithm devised by Christian Zeller to calculate the day of the week for any Gregorian calendar date. The weird formula is given as follows.
is the day of the month
is the month number, where March = 1, April = 2, ..., December = 10, January = 11, February = 12
is the last two digits of year, using the previous year for January and February
is the first two digits of year
mod 7 represents the remainder after dividing by 7, to find the day of the week where Sunday = 0, Monday = 1, ..., Saturday = 6.
Let's see some examples. March 10, 2014 corresponds to
and this leads to so that the date was Monday. Another example, February 10, 2010 corresponds to
because comes from the previous year for February (which is 2009). This leads to , so that the date was Wednesday. Now simple questions arise naturally,
Let's find out.
1. Weird counting on the month number.
Let's first note the reason for the odd handling of months. Why not starting from January? This is because we want leap day not to affect the formula, so we move it to the end of the 'year', and act as if the year began on March 1. (You know Feb 29...)
2. Strategy Behind the summations
Note that in defining , all we care about is the remainder after dividing, so it will be enough to make sure that increases by 1 whenever the day of the week advances by one day; we don't care about the actual value of . So it is enough to add or subtract all the factors effecting the day of the week in order to make the formula valid.
3. Affect of Year
Normally, 1 year is equivalent to 365 days. Since , each normal year advances the day of the week by 1, so nothing more to manipulate! Just put the year number in the formula.
4. Affect of Leap year
But we have to adjust this to account for leap years. Every four years we have an extra day (a year that is divisible by four), so we'll want to add 1 to f. This is done by adding , since this increases by 1 only when d becomes a multiple of 4, which is a leap year. So now we have
5. Affect of Years ending with 00
But according to Gregorian Calendar rule, not every year that is exactly divisible by four is a leap year. We must exclude years that are exactly divisible by 100 but not with 400. That is, we must exclude years ending with 00 but not ones that are divisible by 400.
Every century contains 100 years, 24 of which normally are leap years (excluding ones with 00 end). So typically, each century the day advances by
days. Therefore the day of the week goes back 2 days. Each century can be represented as the first two digit of year (17th century is the collection of years starting with two digits 16, 20th century is the collection of years starting with two digits 19). So we must modify our formula to
where is the first two digits of the year.
Also the years ending with 00 but not divisible by 400 are the ones that is divisible by 4, so we must add the term
as we did for leap years (same argument actually).
6. The Hardest Part
Now we must consider months and days. Consider, for each month, how many days it has beyond 28, then add that up to see the effect the months have on the day of the week. The reason of choice of 28 as the reference is that it is divisble by 7 (not affecting the day of the week).
|# of days||31||30||31||30||31|
Here, we don't have to worry about leap years because we already considered them on previous sections. The number of accumulated days is counted at the start of the month, so if we divide it by 7, the remainder shows how many weekdays the start of the month is from the starting day for the 'year'. Notice the pattern in the excess: 3,2,3,2,3 repeats every five months, and the accumulation reaches 13 in that time. So every 5 months, we want to add 13 days. This can be modeled by the equation of the form
where is the constant that should be determined from specific values in accumulated days. Let's solve this.
Beyond 5 is just repetition, so those are rebundant information. Now,
Any number in the half open interval is valid. For convenience, let's take , so that
(The reason behind this choice is stated in Section 7). Now the modified equation for is
7. The Final Adjustment
Finally, we have to add the day, since each day obviously adds one to the day of the week. Thus
Are we done? Well, no. Nothing we've done so far actually determined which day we start the whole pattern on. Any initial condition should be given. I'll choose today, August 30, 2018. Today is Thursday so that . Calculation gives
Now the adjustment, is nothing but adding 2! (This is the reason why we chose -11/5 as ). Therefore the ultimate equation for the day of the week is
As you can see, the equation is valid as long as Gregorian Calendar rule does not change. Great!
Formula looks dirty but idea is simple... Just follow the Gregorian Caldener rule! Straightforward enough.
Lastly I will post my implementation of Zeller's formula using Python.
def Zeller(D, M, Y): # Preprocess Year if Y < 1582: return 'Before Gregorian' # Define m if M < 3: m = M + 10 else: m = M - 2 # Define k k = D # Define d if m > 10: d = int(str(Y - 1)[-2:]) else: d = int(str(Y)[-2:]) # Define c c = int(str(Y)[: 2]) print (k, m, d, c) L = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] f = (k + (13*m-1)//5 + d + (d//4) + (c//4) - 2 * c) % 7 return 'The date of the week is '+ L[f] #-------------------------- D, M, Y = map(int, input('Enter specific date in DD/MM/YYYY form: ').split('/')) print (Zeller(D,M,Y))