The Doomsday rule

A few months ago I came across the name of J. H. Conway: you’re wondering who the hell he is. Well, Conway is an English mathematician active in the theory of finite groups, knot theory, number theory, combinatorial game theory and coding theory. He has also contributed to many branches of recreational mathematics and he is the invention of the Game of Life. Ah, I was forgetting one last thing: he is currently Professor Emeritus of Mathematics at Princeton University in New Jersey1. Ok. let’s respect this guy but…what would I talk to you about? Well, in this article I will talk about a magic trick: the Doomsday rule.

A brief history

Who has ever heard of it? No ones? Ok, the first thing to know is that the Doomsday rule is an algorithm of determination of the day of the week for a given date. This f****ng unbelievable trick of mind will allow you to win so many bets during the Christmas holidays that you will be envied by your nephews, close friends, neighbors, lovers and even your pets.

The mental calculation was devised by J. H. Conway in 1973: I don’t know how much a mentalist you have to be to trust this method, but the algorithm actually returns the correct answer: if you want to discover more about how it works, go ahead. If you want to try to discover how the algorithm works starting from the code, here my repo with a Ruby implementation of the algorithm.

The algorithm

First of all, a big picture of how the algorithm works in three steps:

  • step 1: determination of the anchor day for the century,
  • step 2: calculation of the doomsday for the year from the anchor day,
  • step 3: selection of the closest date out of those that always fall on the doomsday, e.g., 4/4 and 6/6, and count of the number of days (modulo 7) between that date and the date in question to arrive at the day of the week;

What?! Do you understand something?! Because if not, you really have to know that…Conway can usually give the correct answer to question like “what day of week was the 13 February 1867?”, in under two seconds2. If you’re thinking that probably this is the main reason why you’re reading this blog and he’s Professor Emeritus of Mathematics at Princeton University, well, you’re right.

In any case, since I’m a computer scientist, and I have absolutely no desire to count things in mind nor to open a calendar or search on google for my quiz-date, I have implemented the Conway algorithm for the calculation of Doomsday using Ruby.

Preliminary explanation

This algorithm involves treating days of the week like numbers modulo 7: Conway often suggests - in his course in Princeton called “How I will literaly blow your mind” - thinking of the days of the week as “Noneday”; or as “Sansday” (for Sunday), “Oneday”, (for Monday, it sounds similar), “Twosday”, “Treblesday”, “Foursday”, “Fiveday”, and “Six-a-day”. It doesn’t matter, because there are tables with - wait for it - Doomsdays for the Gregorian calendar, or what I call “The Year Doomsday”. Like the one below:

Mon.Tue.Wed.Thu.Fri.Sat.Sun.Mon.Tue.Wed.Thu.Fri.Sat.Sun.
189818991900190119021903190419051906190719081909
19101911191219131914191519161917191819191920
19211922192319241925192619271928192919301931
193219331934193519361937193819391940194119421943
19441945194619471948194919501951195219531954
19551956195719581959196019611962196319641965
19661967196819691970197119721973197419751976
19771978197919801981198219831984198519861987
198819891990199119921993199419951996199719981999
20002001200220032004200520062007200820092010
20112012201320142015201620172018201920202021
20222023202420252026202720282029203020312032
20332034203520362037203820392040204120422043
204420452046204720482049205020512052205320542055
20562057205820592060206120622063206420652066
20672068206920702071207220732074207520762077
20782079208020812082208320842085208620872088
208920902091209220932094209520962097209820992100

So…for a day, be a doomsday is a properties - at least - related to years. For instance, doomsday for the current year in the Gregorian calendar (2017) is Tuesday. The Conway algorithm works because it is possible to easily find the day of the week of a given calendar date by using a nearby doomsday as a reference point. To help with this, Conway findout that there is a list of easy-to-remember dates…for each month…

that always land on the doomsday of the given year: O.M.G.

What does it means? It means that, for instance, the last day of February defines a doomsday. Or January, January 3 is a doomsday during common years and January 4 a doomsday during leap years, and so on. What the hell of magic days are these doomsday?!? We will explain how the Doomsday for a year is computed. For now, let be the following table a month table that correspond always to the doomsday.

MonthDoomsdays
January3, 31 (solar year) 4 (leap years)
February7, 14, 21, 28 (solar year) 1, 29 (leap years)
March7, 14, 21, 28
April4
May9
June6
July11
August8
September5
October10
November7
December12

Step 1 aka finding a year’s base day

First of all, ask for a day

print 'Insert day:   '
day   = gets.to_i
print 'Insert month: '
month = gets.to_i
print 'Insert year:  '
year  = gets

Then, given

$$c = year’s ; century + 1 $$

(for instance, \(c(2017) = 20\)), then compute:

$$\Big{\Big[\Big(5c + \left \lfloor{\frac{c - 1}{4}}\right \rfloor\Big) ; mod ; 7\Big] + 4\Big} ; mod ; 7$$

My really unefficient implementation of the formula using Ruby is:

baseDay = (((5 * (year[0, 2].to_i + 1)) + (year[0, 2].to_i / 4).ceil % 7) + 4) % 7
puts baseDay

For example, the base day for the 21st century is Tuesday, because:

$$\Big{\Big[\Big(5 x 21 + \left \lfloor{\frac{21 - 1}{4}}\right \rfloor\Big) ; mod ; 7\Big] + 4\Big} ; mod ; 7 = 2 = ; Tuesday$$

Step 2 aka finding a year’s Doomsday

Let be:

$$y = year’s ; last ; 2 ; numbers $$

(for instance, \(y(2017) = 17\)), to determine the Doomsday of the year compute:

$$\Big[\Big(\left \lfloor{\frac{y}{12}}\right \rfloor + y ; mod ; 7 + \left \lfloor{\frac{y ; mod ; 12 }{4}}\right \rfloor \Big) ; mod ; 7\Big] + year’s ; baseday = ; year’s ; Doomsday$$

A possible implementation of the formula using Ruby is:

doomsday = (((year[2, 4].to_i / 12).ceil + (year[2, 4].to_i % 12) + ((year[2, 4].to_i % 12) / 4).ceil) % 7) + baseDay
puts doomsday

For example, the Doomsday of the year 1966 is Monday, because:

$$\Big[\Big(\left \lfloor{\frac{66}{12}}\right \rfloor + 66 ; mod ; 7 + \left \lfloor{\frac{66 ; mod ; 12 }{4}}\right \rfloor \Big) ; mod ; 7\Big] + 3 = 8$$

In 2010, a simpler method - remember, less than two seconds - was discovered to find the year’s Doomsday. It has been shown that this method, more formaly called “Odd + 11”, is equivalent in formulas to compute:

$$\Big[\Big(y + \left \lfloor{\frac{y}{4}}\right \rfloor \Big) ; mod ; 7 \Big] + year’s ; baseday = ; year’s ; Doomsday$$

This formula is particularly suitable for mental calculation, because it does not involve divisions and the procedure, as a recursive one, is easy to remember. So alternatively, to determine the doomsday it is also possible to add the last two digits of the year (y) to the quotient of the division between y and 4. In fact, also following this simpler formula, the Doomsday of the year 1966 is Monday:

$$\Big[\Big(66 + \left \lfloor{\frac{66}{4}}\right \rfloor \Big) ; mod ; 7 \Big] + 3 = 8$$

Step 3 aka finding the day of the week of the desired day

After you know the Doomsday of the year in question, the calculation of the day of the week of the desired day is very simple:

  • identify the Doomsday closest to the chosen day,
  • subtract the date of the nearest doomsday from the date to be identified,
  • add the value of the Doomsday of the year,
  • and finally report the result obtained in base 7;

Ok, let’s start from the…what!? How do you identify the Doomsday closest to the chosen day?! Ok, do you remember the table with the doomsday for each month I talked about before? The only thing you have to do is deal with some comparison between the month and some simple computation between abs difference. A possible implementation of the formula using Ruby is:

### Step 3 - find the day of the week

nearest = 9999999999

case month
	when 1
		if ((year % 4 == 0) and (year % 100 != 0)) or (year % 400 == 0)
			nearest = 4
		else
			[3, 31].each {
				|val|
				if (day-val).abs < nearest
					nearest = val
				end
			}
		end
	when 2
		ddays = [1, 29]
		if ((year % 4 == 0) and (year % 100 != 0)) or (year % 400 == 0)
			ddays = [7, 14, 21, 28]
		end
		ddays.each {
			|val|
			if (day-val).abs < nearest
				nearest = val
			end
		}
	when 3
		[7, 14, 21, 28].each {
			|val|
			if (day-val).abs < nearest
				nearest = val
			end
		}
	when 4
		nearest = 4
	when 5
		nearest = 9
	when 6
		nearest = 6
	when 7
		nearest = 11
	when 8
		nearest = 8
	when 9
		nearest = 5
	when 10
		nearest = 10
	when 11
		nearest = 7
	when 12
		nearest = 12
	else
		nearest = 9999999999
end

And that’s all: you are are done! In fact, the following three points of this third step can be computed with the following line:

weekday = (day - nearest + doomsday) % 7

And of course you can pretty print the result with something really dirty and compact like:

puts "~~~~~~~~~~~~~~~~~~~~~~~"
puts ['January', 'February', 'March',
	  'April', 'May', 'June', 'July',
	  'August', 'September', 'October',
	  'November', 'December'][month-1]+
	  " "+day.to_s+", "+
	  year+" was "+['Monday', 'Tuesday',
	  				'Wednesday', 'Thusday',
	  				'Friday', 'Saturday',
	  				'Sunday'][weekday-1]

For example, to calculate the September 13, 2011:

  • the nearest Doomsday is 5/9;
  • 13 - 5 = 8
  • 8 + 1 = 9 (the 2011 Doomsday was Monday, so the corresponding value is 1)
  • 9 mod 7 = 2 = Tuesday

Thank you everybody for reading!


  1. John Horton Conway ↩︎

  2. Do not worry: it’s not an innate ability!! To improve his speed, he practices his calendrical calculations on his computer, which is programmed to quiz him with random dates every time he logs on. ↩︎