# Calculate which day of the week a date falls in using modular arithmetic

In Summer Wars the main character (he is a mathematician) calculates the day of the week of someone's birthday (19/07/1992 is Sunday). I know (very) basic modular arithmetic but I can't figure out how to do it. Can someone point me to the right direction? It seems fun to do.

• en.wikipedia.org/wiki/Doomsday_rule – t.b. Jan 10 '11 at 3:56
• I actually teach this algorithm in my algorithms class; it's useful in real life to be able to do this! – Fixee Apr 20 '11 at 3:54
• Dershowitz/Reingold is the go-to book for topics like these. – J. M. is a poor mathematician Apr 20 '11 at 4:56
• I wonder if O’Beirne’s algorithm (sixthform.info/maths/?p=155) to find the date of Easter Sunday is based (at least partialy) on this one. – Américo Tavares May 12 '11 at 23:39
• Ah, Conway… "I’m sorry, I’m used to saying “naught”. I’ll try to say “zero”. (pause) No, I won’t try. You can all just learn to be naughty." – Akiva Weinberger Sep 8 '15 at 23:49

The Zeller congruence is yet another method for reckoning the day of the week of a given date. Kim Larsen presents an implementation of a variant of the Zeller congruence in this article. (There is additional discussion of Larsen's formulation here.)

Before the Doomsday method (see link in Theo Buehler's comment), there was a formula due to Gauss. A good write-up is Berndt Schwerdtfeger, Gauss' calendar formula for the day of the week, available at http://berndt-schwerdtfeger.de/cal/cal.pdf

Zeller's Congruence, modified for modern computing conventions, provides a simple algorithm for determining day of the week for any day of the Gregorian Calendar, which came into use in 1582. The simplest variation of the formula is this:

h = (d + ((m+1)*26)/10 + y + y/4 + 6 * (y/100) + y/400 + 5) % 7 + 1; where d is the day of the month, m is the month, y is the four-digit year, and the result uses ISO day-of-week conventions: 1=Monday to 7=Sunday.

All division operations must use integer (truncating) division. This variant uses only positive coefficients, so it avoids problem with negative results that show up in other variants.

Month and year must be handled differently for the first two months of the year. January and February must be treated as months 13 and 14 of the previous year. So the first month becomes March, with a value of 3. A Java implementation might look like this:

/**
* Calculate the day of the week for a given date of the Gregorian Calendar.
* @param year The four-digit year
* @param month The month, from 1 (January) to 12 (December)
* @param dayOfMonth The day of the month.
* @return An ISO-compliant day of the week, where 1 = Monday and 7 = Sunday.
*/
public final int dayOfWeek(int year, int month, int dayOfMonth) {
assert year > 1582 : "Four digit year required: " + year;
int y = year;
if (month < 3) {
month += 12;
y--;
}

return (dayOfMonth + ((month+1)*26)/10 + y + y/4 + 6 * (y/100) + y/400 + 5) % 7 + 1;
}


A thorough article about the formula may be found in Wikipedia's Zeller's Congruence article

It's easy without invoking any special formulas by not only doing arithmetic modulo 7, but in that same spirit also use the same logic for the months. E.g. why let August end on 31st of August? it's convenient to extend August into September and define 32 August as being equivalent to 1st of September.

To compute how many days have passed modulo 7 since the 19th of July 2015 (today is Wednesday 9th of August 2015), I can consider today to be the 40th of August, so it's 40 + 12 days, modulo 7 this is 3. Then we know that 365 = 1 mod 7, so if we forget about leap years the 23 years that have passed would make this 3 + 23 Mod 7 = 5 weekdays earlier. Each leap year makes an additional contribution of 1 day. In a time span of 4 years there is one leap year with the exception of years divisible by 100, but not years divisible by 400. So, we don't need to worry about the year 2000, this was the exception to the exception. To count the number of leap years, we can then simply consider the first one that falls in the time interval we're considering and that's the year 1996. One can then divide the time interval since 29th of February 1996 and divide that by 4 years and round and round it to the next integer. But it's simpler to just consider that the last leap year in the interval was 2012 and that therefore you had 16/4+1 = 5 leap years.

So, we add 5 to the 5 days without leap years and take mod 7 to obtain 10 Mod 7 = 3. Now 3 weekdays days before Wednesday is indeed a Sunday.