The day of the week for any date can be obtained from the following two data items :
A. The ordinal position of the
day within the year (e.g. March 25, 1999 was day 84). We'll call this
the year_ordinal.
B. The ordinal position of the day within
the week for January 1 of that year (where Sunday is 1, Monday is 2 etc.).
The ordinal position of the day within the week we'll call the week_ordinal and week_ordinal for January 1 we'll
refer call week_ordinal(1/1). This value depends on the year.
Given these two numbers, year_ordinal (the ordinal position of day within the year) and week_ordinal(1/1) (the ordinal position of January 1 within the week), the week_ordinal for any date is easily found by the formula
((year_ordinal - 1) + (week_ordinal(1/1) - 1) ) modulo 7 + 1
Essentially you start at the ordinal position of January 1 with in the week and increment it by the ordinal position of the day within the year minus 1 (modulo 7) then add 1 to obtain ordinal position of the day within the week.
For example, if the January 1 of the year was a Wednesday (day of week 4) and you wanted to find the day of the week January 12 fell on (day number 12) then starting at 3 you count forward 11 units (modulo 7)
3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0
You end up at 0. Adding 1 to 0 yields 1 so January 12 is a Sunday. You can check that this works using the calender below by starting at Wednesday the 1st and counting forward 11 days to arrive at Sunday!
Su M Tu W Th
F Sa
1 2 3 4
5 6 7 8
9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Calculating the year_ordinal is easily done if we make use of the following table which lists the number of days before the 1st of each month
Month
Number of Days
before 1st
Jan
0
Feb
31
Mar
59*
Apr
90*
May
120*
Jun
151*
Jul
181*
Aug
212*
Sept
243*
Oct
273*
Nov
304*
Dec
334* Note : *
indicates add 1 for leap years
This table is obtained by summing the days of all prior months.
The year ordinal for any date is obtained by adding the proper value for that month from the table to the day.
Example
June 15, 2003 is day 166 (151 + 15).
Since 365 is not divisible by 7 but 365 equals 52 times 7 plus 1, the ordinal position of the day within the week for January 1 advances by 1 day from one year to the next except when the previous year was a leap year in which case it advances by 2 days.
Example
Since January 1, 1998 fell on a Thursday, January 1, 1999 fell on a Friday since there are 365 days between them.
Since January 1, 2000 fell on a Saturday, January 1, 2001 will fall on a Monday since there are 366 days between them.
Given that the January 1 advances one day except when going from a leap year in which case it advances two days, it's not difficult to show that there is a 28 year cycle for determining the day for January 1. Consider the years 1901 through 1928. The cycle starts with Tuesday, January 1 1901. Years in red indicate where the ordinal position advances by 2
1901 - Tu 1902 - W
1903 - Th 1904 - F
1905 - Su
1906 - M 1907 - Tu 1908 - W
1909 - F
1910 - Sa 1911 - Su 1912 - M
1913 - W
1914 - Th 1915 - F 1916 - Sa
1917 - M
1918 - Tu 1919 - W 1920 - Th
1921 - Sa
1922 - Su 1923 - M 1924 - Tu
1925 - Th
1926 - F 1927 - Sa 1928 - Su
1929 - Tu 1930 - W 1931 - Th 1932 - F
As is shown, the pattern repeats with 1929. The cycle is 28 years long.
Since the cycle repeats every 28 years, if we calculate the difference between
the current year and 1901 modulo 28, we will know where we are within the
28 year cycle. Using the formula we obtain
a = (year - 1901) modulo 28
where a is in integer between 0 and 27.
Example : For the year 2000,
(2000 - 1901) modulo 28 equals 15.
and if you count 15 forward from 1901 - Tu (1902 - W is 1, 1903 - Th is 2 etc) you end up at 1916 - Sa. So January 1, 2000 was a Saturday.
There is a trick we can used to calculate the day instead counting forward on the 1901 - 1928 table. Given any year , the value of a that we calculate is the offset into the 28 year cycle. And if we did not have to take into account the effect of leap years, if we added a to the to the first day value for 1901 modulo 7, we would have the first day for the year; that is calculate (3 + a) mod 7.
However this does not take into account the effect of leap years which pushed January 1 ahead two days instead of 1. So if we add the number of leap years in the cycle, b where
b = floor (a / 4)
the sum of a plus b modulo 7 tells us how many days we have to advance January 1 from Tuesday. Since modulo 7 returns a value between 0 and 6 and we normally number the days of the week 1 (Sunday) through 7 (Saturday), we have to add 1.
week_ordinal(1/1) = (2 + a + b) modulo 7 + 1
Thus the week_ordinal(1/1) can be found by the three formulas
1. a = (year - 1901) mod 28
2. b = floor(a/4)
3. week_ordinal(1/1)
= (2 + a + b) modulo 7 + 1
To find the ordinal position of the day within the week for any date between Jan 1, 1901 and Dec 31 2099
1. Find the year_ordinal using the table of days before the first of the month
2. Calculate week_ordinal(1/1) as follows
a = (year - 1901)
modulo 28
b = floor (a/4)
week_ordinal(1/1) = (2 + a + b) modulo 7 + 1
3. Day of the Week = ((year_ordinal - 1) + (week_ordinal(1/1) - 1)) modulo 7 + 1
1. This algorithm only works for the dates between 1901 and 2100. The fact that 2100 is not a leap year prohibits the 28 year cycle for obtaining the first day from carrying over into the 22nd century.
2. The algorithm presented makes use of modular arithmetic with its use of modulo 28 and modulo 7 calculations. In modular arithmetic it's easier to starting counting at 0 instead of 1. Consequently the algorithm could be simplified if we made the following changes
a. Number the days from 0 to 6 with Sunday being day 0 and Saturday being day 6
b. Number the days of the year from 0 to 364 (or 365 for leap year) with January 1 being day 0 etc.
Number the days of the week 0 - 6 and the days of the year 0 - 364 (or 365 for leap year)
1. Find the year_ordinal using the table of days before the first of the month except subtract 1 from this value. This would number the day of the year from 0 to 364 (or 365 for leap years)
2. Calculate week_ordinal(1/1) as follows
a = (year - 1901) modulo 28
b = floor (a/4)
week_ordinal(1/1)
= (2 + a + b) modulo 7
We note that Tuesday January 1, 1901 is now day 2 under the new numbering (Sunday is day 0)
3. Day of the Week = (year_ordinal + week_ordinal(1/1)) modulo 7
Example : Find the Day of the Year for March 21, 2004
1. March 21, 2000 is day 60 + 21 - 1 = 80
2. a = (2004 - 1901) modulo 28 =
19
b = floor (19/4)
= 4
week_ordinal(1/1) = (2 + 19 + 4) modulo 7 = 4 (Thursday)
3. week_ordinal(3/21/2004) = (80+4) modulo 7 = 0 (Sunday)