Converting a Month-Date-Year to the Day of the Week

I read this a long time ago in a book, and I've used it to amuse my friends over the years, even raced one to come up with the answers first. It's basically a parlor trick that is completely useless, since it's hard to verify without a perpetual calendar (though such things are easily obtainable).

General algorithm

  1. Pick a base year and find out (with a perpetual calendar, probably) what day of the week January first was in that year. I use 1900, but you can pick pretty much any year you want.
  2. Count the number of years since that year. Since there are 365 days in a year, and 365 = 52 * 7 + 1, a month/day combination shifts forward one day per year.
  3. Count the number of leap years (including the current year) since the base year (include the base year, if applicable). Every leap year of course adds one extra day. Note the rule for determining whether a year is a leap year, below.
  4. Add in a "magic" number that offsets for the month within the year. It's not really magic, but it can seem that way. What you do is assign a number to January that corresponds to the day of the week it started on in your base year. I want my answer to come out as a number between 0 and 6 (inclusive), with 0 indicating Sunday. Since 1900 began on a Monday, I give a 1 to January. Then you can compute the "magic" values for the remaining months by simply adding the number of days in the current month (28 for February; we already took care of leap years in step 3) to the number for the current month and computing the result modulo 7. (See below if you don't know modular arithmetic.) So my numbers are 1, 4, 4, 0, 2, 5, 0, 3, 6, 1, 4, 6.
  5. Add in the day of the month.
  6. If the date in question is in a leap year, but before February 29th, we added in an extra day in step 3, so subtract one.
  7. Compute the modulus-7 value of the sum of the numbers in steps 2-6.
  8. You now have a value between 0 and 6, inclusive. 0 indicates Sunday, 1 indicates Monday, etc.
Yuck, huh? Well, here's a C program that computes exactly that. It's really simple on a computer.

Doing it in your head

The real fun is when you can do this in your head and always get it right. The general algorithm above works fine, except that for certain years, the numbers get kind of big and hard to remember. So here's a modified algorithm that should be easier to keep in your head. I'll assume that we are going to use 1900 as the base year (should cover most birthdays, which seems to be the popular request).
  1. Divide the last two digits of the year by 12 with integer division, getting a quotient and a remainder. Come on now, you did this in grade school - it's not hard. Add those two numbers, modulo 7.
  2. Divide the remainder found in step 1 (not the sum, the remainder from the division) by 4 and get the quotient. (We don't need this remainder.) Add it to the sum found in step 1 and again take the modulus-7 result.
  3. Add in the value assigned to the desired month:
    January 1
    February 4
    March 4
    April 0
    May 2
    June 5
    July 0
    August 3
    October 1
    November 4
    December 6

    If you are in to math and recognize the three-digit patterns of perfect squares and that helps you remember this step, use that. Otherwise, just memorize those numbers or memorize how they were created (see step 4 in the general algorithm).

    Compute the modulus-7 result.

  4. Add in the day of the month and compute the modulus-7 result.
  5. If you are in a leap year but before February 29th, subtract one, modulus 7.
And once again you've got a number between 0 and 6 inclusive, where 0 indicates Sunday, 1 indicates Monday, etc.

You can shift it to 1800 by changing the magic numbers for the months. That year, 1 January was a Wednesday, so add 2 (modulo 7) to the numbers. 1 Jan 1700 was a Friday, but for dates prior to 14 Sep 1752, things get messy anyway, since that was when the British government added days to the calendar to account for the new information about the length of the year. (14 Sep 1752 immediately followed 2 Sep 1752.)

So you think you've got it, huh?

All right, let's try it out. Compute the day of the week for a month, date, and year. Then enter the values below and see how you did. You may enter the year as a four-digit number or relative to 1900 (e.g. 97 will be assumed to be 1997, 110 will be assumed to be 2010).

If you aren't sure, keep track of where you are at every step of the way. It will be printed out on the answer page.

Date: Month: Year:

Why the shortcuts work

The shortcuts are really pretty simple. One trick is to use the modulus operator a lot more often. That helps keep the numbers smaller. The other trick is how we count years and leap years.

We divide by 12 because in every block of 12 years, there are 3 leap years (as long as we avoid nasty century breaks - see below about rules for determining whether a year is a leap year). That means that every block of twelve years pushes a month-day combination forward 12 days for the 12 years and 3 (extra) days for the 3 leap years, or ( 12 + 3 ) mod 7 = 1 day forward. That's a nice round number. That's what the quotient in step 1 tells you. The remainder in step 1 tells you how many extra years there are inside the last (incomplete) block of twelve. The division by 4 in step 2 tells you how many of those years in the incomplete block are leap years. The last two steps are the same as before.

Rules for determining leap years

A year is a leap year if So
1996 was a leap year because 1996 / 4 = 499 (no remainder)
1997 was not because 1997 / 4 = 499 remainder 1
1900 was NOT a leap year because although 1900 / 4 = 475, 1900 / 100 = 19
2000 IS a leap year because 2000 / 4 = 500, 2000 / 100 = 20, and 2000 / 400 = 5

Modular arithmetic

Modular arithmetic is the technical term in number theory for determining the remainder of a number in integer division. (Actually, the theory of equivalence classes is MUCH more general, but you can go to the library if you really want to know all that.) In this case, I don't really care, for example, how many weeks have passed, I only want to know the day within the week. Thus there are only seven values of interest. I can arbitrarily assign the values of 0-6 to these seven desired results, and also arbitrarily assign 0 to be a particular result. The way it works is basically to take the number and compute the remainder when you divide by 7. Don't let the addition operations required confuse you. You can do them as usual, then compute the modulus. For example:

3 + 2 = 5 mod 7    (same as always since 5 < 7)
6 + 3 = 2 mod 7 (6 + 3 = 9, 9 / 7 = 1 remainder 2)
and so on. Equivalence classes are a very powerful concept, but this is really a simple application. Just remember back in first or second grade when you first did division - you probably did exactly this without realizing it. It really is that simple.