on May 28, 2011, barcelona beat manchester united 3–1 at wembley stadium to win the champions league final — a match that made playing against lionel messi look almost unfair.
but i have a different question about that night: what day of the week was May 28, 2011?
was it monday? friday? my first guess was sunday.
by the end of this article, you’ll be able to answer that question — not just for this match, but for almost any date — using a few simple techniques.
how calendar works ?
the most famous calendar people are using for their birthdays is the international standard solar dating system called the gregorian calendar. it was created by Pope Gregory XIII to replace the older Julian calendar established by Julius Caesar in 46 BCE.
a normal year has 365 days. divide that by 7 and you get 52 weeks with one day left. a leap year has 366 days, so there are two days left. these small leftovers are why dates move around the week.
and since february likes to be different, it gets the extra day in a leap year. a year divisible by 4 is usually a leap year, but if it is divisible by 100 it must also be divisible by 400. so 1900 was not a leap year, but 2000 was. keep this rule somewhere in your head. we will need it.
what does this have to do with messi ?
nothing yet. but think about this. if a date is a monday, what day is it 7 days later ? still monday. 14 days later ? monday again.
so we do not need to count every single day. we can throw away complete weeks and only count what is left. 19 days ahead is the same weekday shift as 5 days ahead, because the other 14 days are two complete weeks.
how you can do it
the mathematician John Conway came up with a method called the doomsday rule. dramatic name for something you can use to find out what day your birthday was.
the idea is that some easy dates always share the same weekday within a year. that shared weekday is the year’s doomsday. it can be monday in one year and a different day in another.
start with these: april 4, june 6, august 8, october 10 and december 12. nice and easy. 4/4, 6/6, 8/8, 10/10 and 12/12.
for the other months, remember may 9 and september 5, then july 11 and november 7. the numbers swap places.
march 14 is another one. for february use its last day, either the 28th or 29th. january is the one to watch: january 3 in a normal year, january 4 in a leap year. you can check the full list here.
why do these dates stick together ? count from april 4 to june 6. it is 63 days. exactly 9 weeks. the same idea connects the other dates.
okay, but how do we find the year’s doomsday ?
first give the weekdays numbers: sunday = 0, monday = 1, tuesday = 2, wednesday = 3, thursday = 4, friday = 5 and saturday = 6.
we also need a starting number for the century. for 1800–1899 use 5, for 1900–1999 use 3, for 2000–2099 use 2, and for 2100–2199 use 0. these century anchors repeat every 400 years, so 1600–1699 uses the same number as 2000–2099.
here is a simple way to do the calculation. take the last two digits of the year, add the number of complete groups of 4 in those digits, then add the century’s starting number. divide the total by 7 and keep only the remainder.
let’s use 2011. the last two digits are 11. there are 2 complete groups of 4 in 11. our century starts with 2.
11 + 2 + 2 = 15.
remove 14, which is two complete weeks, and we have 1 left. 1 means monday. so the doomsday for 2011 is monday.
if you are wondering where the calculation comes from, each ordinary year shifts the doomsday by one weekday, and each leap year adds another shift. the groups of 4 count those extra shifts within the century. the century anchor handles where we started.
back to wembley
we now know that may 9, 2011 was a monday. may 16 was also monday. may 23 was also monday.
five more days gets us to may 28. tuesday, wednesday, thursday, friday, saturday.
so the answer is saturday. barcelona won the final on a saturday. my sunday guess was not even close enough to get a point.
one more before you go
what about february 29, 2024 ? take 24, add 6, then add 2 for the century. that gives us 32. remove 28 and we have 4, which is thursday.
2024 is a leap year, so february 29 is itself a doomsday. the answer is thursday. no extra counting needed.
one small detail: this method uses the gregorian calendar. for old historical dates, check which calendar the country was using at the time before applying it.
let the computer do it: monday first in C#
now suppose you want to put this in a program. another approach is to count the days from january 1, year 1, which is a monday when we extend the gregorian calendar backward. this is a calendar convention, not a claim that people used this calendar back then.
give that starting date the number 0. count the complete years before our date, add their leap days, then add the days already passed in the current year. divide by 7 and keep the remainder. monday is 0, tuesday is 1, and so on until sunday is 6.
so here monday is the first day in our numbering. in the doomsday explanation above, sunday was 0. the weekday stays the same; only its number changes.
the before array below stores the days before each month in a normal year. january has 0 days before it, february has 31, march has 59. if the date is after february in a leap year, we add one more.
using System;
public class WeekdayExample
{
// Monday = 0 through Sunday = 6.
public static int MondayFirst(int year, int month, int day)
{
// Validate the date before using it as an array index.
DateTime date = new DateTime(year, month, day);
int[] before = {0,31,59,90,120,151,181,212,243,273,304,334};
int previous = date.Year - 1;
int days = 365 * previous + previous / 4
- previous / 100 + previous / 400;
days += before[month - 1] + day - 1;
if (month > 2 && DateTime.IsLeapYear(year)) days++;
return days % 7;
}
public static void Main()
{
string[] names = {"monday","tuesday","wednesday","thursday",
"friday","saturday","sunday"};
Console.WriteLine(names[MondayFirst(2011, 5, 28)]); // saturday
Console.WriteLine(names[MondayFirst(2024, 2, 29)]); // thursday
}
}
for may 28, 2011, this counts 734284 days after our starting monday. the remainder after dividing by 7 is 5. with monday at 0, 5 means saturday. same answer, different route.
if you only need the answer in a real C# application, DateTime.DayOfWeek already does the work. convert its sunday-first numbering with ((int)date.DayOfWeek + 6) % 7. writing the calculation ourselves here helps us see why it works.
both methods in C
let’s put them next to each other. monday_first counts elapsed days. doomsday follows the anchors we used in our heads. both functions below return monday = 0 through sunday = 6, so we can compare their answers directly.
the century formula gives the same anchors listed earlier. the double remainder in doomsday handles dates before a month’s anchor, because a negative value % 7 can stay negative in C. the final + 6 changes sunday-first numbering into monday-first numbering.
these C functions assume a valid date with a year from 1 to 9999. validate user input before calling them. the C# example uses DateTime to reject invalid dates.
#include <stdio.h>
int leap(int y) {
return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
}
/* Both methods expect a valid Gregorian date, years 1..9999.
Both return Monday = 0 through Sunday = 6. */
int monday_first(int y, int m, int d) {
const int before[] = {0,31,59,90,120,151,181,212,243,273,304,334};
int previous = y - 1;
int days = 365 * previous + previous / 4
- previous / 100 + previous / 400;
days += before[m - 1] + d - 1;
if (m > 2) days += leap(y);
return days % 7;
}
int doomsday(int y, int m, int d) {
int dates[] = {3,28,14,4,9,6,11,8,5,10,7,12};
int century = y / 100;
int yy = y % 100;
int anchor = (5 * (century % 4) + 2) % 7;
int doom = (anchor + yy + yy / 4) % 7;
if (leap(y)) { dates[0] = 4; dates[1] = 29; }
int sunday_first = ((doom + d - dates[m - 1]) % 7 + 7) % 7;
return (sunday_first + 6) % 7;
}
int main(void) {
const char *names[] = {"monday","tuesday","wednesday","thursday",
"friday","saturday","sunday"};
const int examples[][3] = {{2011,5,28}, {2024,2,29}, {1900,3,1}};
for (int i = 0; i < 3; i++) {
int y = examples[i][0], m = examples[i][1], d = examples[i][2];
printf("%04d-%02d-%02d: %s / %s\n", y, m, d,
names[monday_first(y,m,d)], names[doomsday(y,m,d)]);
}
return 0;
}
the output is:
2011-05-28: saturday / saturday
2024-02-29: thursday / thursday
1900-03-01: thursday / thursday
that last example is useful because 1900 was not a leap year. february only had 28 days. it is an easy detail to miss if your leap-year check only divides by 4.
now try your own birthday. find the year’s doomsday, choose a nearby date from the list, then move forward or backward. when you are done, check your answer in the terminal at the end of this post. it shows every step, so you can see exactly where you went wrong.
it will probably feel slow the first few times. that is fine. once the dates become familiar, most of the work is just adding small numbers and throwing away weeks.
and next time someone brings up that final, you can tell them it was a saturday. whether a manchester united fan wants to remember it is a different question.