Today is Friday... how can we prove it?

By: tuvrai

In this post I will present an ultimate guide on how to calculate days of the week of the given day mentally in the matter of seconds. All we need is first grade math, some effort and to help ourselves on the journey - some code.

The calendar

So the calendar we use right now is the Gregorian calendar, introduced by Pope Gregory XIII in 1582 as a replacement for Julian Calendar. The latter one was used by over 1600 years - why someone bothered to change it? That's because the amount of days in the astronomical year is not an integer - it's 365 days AND 5 hours, 48 minutes, 45 seconds and 138 milliseconds.

So if we we had a calendar with 365 days and nothing else, we would end up having a season offset of 1 day per 4 years. For instance, after 28 years, the summer would start a week later.

To fix that, the Julian calendar was introduced, giving us a leap year every 4 years. With that system, the offset is now 1 day per 128 years - over a century. But after many, many centuries the drift was significant.

And so Gregorian Calendar was presented as a solution, changing Julian calendar slightly - removing the leap years when the date is divisible by 100, but not by 400. So for example, the years 1800 and 1900 are not leap years (as they would be in Julian system), but 2000, 2400 and so on remain leap years. This system yields 1 day of offset per 3216 years. We can still do better than that, as Matt Parker has shown, but the system was good enough to be adopted by most of the countries, still being used today.

The method

Every date can be uniquely identified by four properties: the day, the month, the century and the year within that century. Each of those maps to a numerical value, which bundled together will give us final numerical value, which maps to some weekday name.

In our method, every week day is a number from 0 to 6. Our zero day will be sunday and the last is saturday - 6. When our final value is bigger than 6, we use modulo arithmetic of 7, as we have 7 days in the week. For example, if we end up with the value 10, we actually have 3 - wednesday.

Su
Mo
Tu
We
Th
Fr
Sa
0
1
2
3
4
5
6

For instance, we will calculate the weekday of 29th July 2022.

The day

This is the simplest component. We can think of it as an offset from last day of previous month, for instance 3rd June is offseted three days from May, 31th. You probably know, that if you have any date and add 7 days to it, you end up with the same weekday in both dates, always.

29th of July has the same weekday as 22.07, 15.07, 8.07 and finally 1.07. So we don't have to take such big number like 29, but just keep 1. Let's keep it and move on.

The month

Every month has a unique, constant value. We start with the base of 0, at January. Let's say we have 1st January and it's monday. As we know, by adding 7 or its multiple, we end up with the same day of the week. So 8th, 15th, 22th and 29nd January will also be monday.

How about 1st February? Since January is 31 days long, the 1st February is 31 days after 1st January, in other words: 4 weeks and 3 days. So we have a constant value of how far the week day of 1st January is from 1st February - it's 3 days. Always. If you think about it further, February 1st is the same day as March 1st (unless it's a leap year, but we'll cover that later).

We can use it now to build the table of months by repeating the process from month to month, ending up with:

Jan
0
Feb
3
Mar
3
Apr
6
May
1
Jun
4
Jul
6
Aug
2
Sep
5
Oct
0
Nov
3
Dec
5

Calculating for January or October would be the best, as whether you substract it or add, it doesn't change anything, basically meaning we can forget about the month coefficient altogether! But our date is in July though, so we happily keep the 6 and move on.

The century

The Gregorian cycle lasts 400 years. The centuries are also somehow circular in this method:
16XY
6
17XY
4
18XY
2
19XY
0
20XY
6
21XY
4

... and so on - we start from 6, down with -2 step until we reach 0. Then we start again from 6.

I deliberately wrote those numbers as 16XY, 17XY etc. instead of 1600s, 1700s. That's because you need to focus on the first two digits itself, rather than a century the year is in. Our century are years 2001-2100, not 2000-2099, but we use latter one to get the century coefficient. Hence, the year 2100, will have coefficient of 4 and the year 2099 will have 2, despite they are in the same 21st century.
We keep the 6.

The year

With a year, we start from base of 0, when the year is XY00. Since the regular year is 365 days long, it's 52 weeks... and one day. That's why, the offset is one day per year. Once in four years though we end up in a leap year. So every 4 years we add value of two instead of 1, because when you think about it: 1st march will be one week day later when 29th February is around, and so the other days of this year, except days in January and February.

The forumla for every year is: Get the value of year (in our case it's simply 22), divide it by 4 and trim it to integer -> 22/4 is 5.5, so we get 5. Then we add the year itself, having: 5 + 22 = 27, which divided by 7 days yields 6.

Leap years

In Gregorian Calendar, the year is leap when it is:
1. divisible by 4
2. not divisible by 100, unless it's divisible by 400
For example, years 2024, 2000 and 1600 are leap, but 1900 or 1800 are not.

In our method, if the year is not leap, we skip this point.

If it is though, you will need to substract the value of 1, but only if the month is January or February. Why only those two? I explained in year property, that we add one every year, but since we have an extra day right before March the 1st, the weekdays of days starting from 01.03 will drift another extra day. So we add two every 4 years to synchronize days after 29th February. But how about the first two months? They still fall into one day offset, and since we added two days to the year, we need to substract 1 for balance.

You can think of it that the coefficient of January and Februray are 6 and 2 respetively if the year is leap.

Just around 4.1% of the dates will be affected by it.

Nevertheless, in July - our example date's month - we don't care about the leap year flag.

Bundling all together

So we've got:
day
1
month
-1 or 6
year
-1 or 6
century
-1 or 6
leap flag
0

You might notice that some cells have two values. This is a very useful trick, if you want to make calculation faster.

So since we have our 0-day at Sunday. If we go 6 days forwards from Sunday, we get to Saturday. But since we don't care about actual calendar days, but just week days, we can also get to Saturday by substracting one day. You can think of every coefficient as weekday distance from Sunday and sometimes substract, sometimes add, as substracting one might be easier that adding six.

So with that in mind, after adding each coefficient, we end up with the final one of -2, which essentialy means:
‘The week day, which is two days before Sunday’- Friday.

If we would add everything, we would get 19. In case we've got bigger number than 6, we need to take the remainder of our value divided by 7, which gives us 5, which means:
‘The week day, which is five days after Sunday’- which is also Friday.

We can even mix substracting and adding, for example we take negative coefficent for year and positive for century, yielding 1+6-1-1 which is 5. You can always convert 6 to -1, 5 to -2 or even 4 to -3, if you want.

That can make our month, year and century coefficients easier also, for example April and July instead of relatively big 6, become -1.

Julian calendar

So the method above is perfectly compatible with the Gregorian calendar, used in modern times since 1582. Some countries adopted it much later though, with Saudi Arabia doing it very recently - just 7 years ago! So let's say we have a date from 17th century from English chronicle - it might be date compatible to Julian calendar, so using our method we won't calculate the weekday properly. We can't use it with any Julian date, like from medieval or roman times either. If you don't care about it, just skip this section.

But since Julian calendar is still very similar to Gregorian calendar (The only difference is that in Julian calendar every year divisible by four is leap, so years like 1700, 1800 or 1900 are leap in Julian calendar, contrary to Gregorian).

So first let's move back in time to 5th october 1582, Gregorian calendar. Oh, actually we cannot do that, because this day never happened. That's because when the Gregorian calendar was adopted, they needed to recompensate the error accumulated by using Julian calendar (Julian calendar is one day late every 128 years) - so they skipped 10 days and after October 4th, October 15th happened.

1582 october calendar
via: Asmdemon, wikipedia.org

Alright, but all we care about are weekdays and as you can see on the graphics above despite skipping 10 days, they didn't change weekday by 3, so after thursday there is still Friday instead of Monday. If this change never happened, 15th October 1582 would be Monday in Julian terms, so we can see that the same day/month/year combination has positive three day offset in Julian calendar compared to Gregorian.

So we can use this knowledge and after calculating the weekday regularly as I taught you earlier, we simply add 3 days to the weekday and we get a weekday in Julian calendar. Keep in mind, that we are talking merely about plain day-month-year combination. Very same day has different combinations in Gregorian and Julian calendar. For example, 29th of March 2023 (Wednesday) in Gregorian is 16th of March 2023 (which is Wednesday also) in Julian calendar.

So we know what to do in 1500s, but what about the other centuries? We need to know, that 29th February 1500 did happen in Julian calendar and wouldn't in Gregorian calendar. So to take this change into account, we need to change our additional Julian coefficient (which is 3 in 1500s). When we go 100 years earlier, we need to lower it by one, so in 1400s the coefficient is 2, in 1300s it's 1 and in 1200s it's 0, but in 1100s it's also 0 - that's because year 1200 would be a leap year in both Julian and Gregorian calendar, so this time our calendar systems don't diverge.

It's more intuitive to do this process by going forward in time. So as we start from 1500s and coefficient 3, as we reach 1600s we still keep coefficient of 3, because year 1600 is leap in both systems. When we reach 1700s though, we need to increment it to 4, then in 1800s to 5 and so on. Let's present it as a table:

Years Gre. coef Jul. coef Overall
2000s 6 6 5
1900s 0 6 6
1800s 2 5 0
1700s 4 4 1
1600s 6 3 2
1500s 0 3 3
1400s 2 2 4
1300s 4 1 5
1200s 6 0 6
1100s 0 0 0
1000s 2 6 1
900s 4 5 2
800s 6 4 3
700s 0 4 4
600s 2 3 5
500s 4 2 6
400s 6 1 0
300s 0 1 1
200s 2 0 2
100s 4 6 3
(-1)-99 6 5 4
(-101)-(-2) 0 5 5
As you can see, when we combine Gregorian century coefficient and Julian coefficient we end up with overall Julian century coefficient we can use, when we encounter a Julian date. For example we can easily calculate weekday of the capture of Constantinopole, 29 May 1453:
day
1
month
1
year
3
century
4
leap flag
0
Bundling together, we have 9. Meaning this event happened two days after Sunday, which is Tuesday.

You might wonder what about dates B.C.E. Well, it's trickier, because as we go backwards in A.D. dates we have a pattern of years like e.g. 4,3,2,1,0,99,98 ..., but with B.C. dates we've got 98,99,0,1,2 and so on - we go in opposite direction. Another fact is that the year zero didn't exist, so from 1 A.D. we go straight to 1 B.C.

To handle that, we can temporary add 100 to dates which are close to B.C./A.D. calendar eras border, so it's easier to see the pattern. I will write A.D. years as positive numbers and B.C. dates as negative:

Year Year+100 Year coef Gre. cent. coef Jul. cent. coef Overall cent. coef
1 101 1 6 5 4
-1 100 0 6 5 4
-2 99 4 0 5 5
-3 98 3 0 5 5
... and so on ...
-100 1 1 0 5 5
-101 0 0 0 5 5
-102 99 4 2 4 6
As you can see, in year B.C. we act like it was year 0, the first year of the interval, just like year 2000 is first year of 2000-2099 interval. 2 B.C. is the last year of the previous interval and since it's different interval - we change the gregorian century coefficient, but we don't change julian coefficient for the same reason it didn't change between 1500s and 1600s A.D. Another interval ends on 102 B.C. and so on.

Nevertheless, calcluating weekdays in B.C. era might not be very accurate. First of all, Julian calendar was introduced in 45 B.C. so calculating weekdays for any year before that is a funny game at best. Secondly, people who managed it made mistakes, like adding a leap year every three years instead of four. Basically, until A.D. era it was a mess. But still, you can have fun calculating. You might checkout this Julian Day calculator provided by nasa.gov (I don't know what's the story behind it).

The improvement

So with the method presented in previous chapter, you will be already able to calculate any date in roughly 20-30 seconds, using month and century coefficients table, as at this point you don't really remember it.

But if you want to impress somebody or compete, you need to do it really quickly. So what you need to do, to make it quick?

Keep in mind, that every date-calculating property comes from a calendar properties itself, so maybe you will discover some patterns independently, just like savants do. Generally speaking though, remembering as much as you can is very helpful. The less you compute in your head, the better. And every fraction of the second could be important.

The training

Now when we are familiar with the ways how to quickly calculate dates, we need to put some time and effort into training, which is essentialy calculating as many weekdays as possible.
And this is where computers help us. I wrote a simple webapp, which will allow us quickly do a lot of repetitions in short period of time.

It allows player guess weekday of random date from year interval 1600 to 2400 (easy to change). We have a UI which allows user training limited either by tries or by time. It also calculate stats of every session.

You can use it here.

You can get the source code here and freely use it and modify it for your preferences.