
Calculate the day of the week for any date in your head - emrehan
http://rudy.ca/doomsday.html
======
bumbledraven
Here's the easiest way I’ve seen [1] to determine if a year is a leap year:

 _If the last two digits of the year are 00, throw them away and keep only the
first two digits. Otherwise, keep only the last two digits. The year is a leap
year if what you kept is divisible by 4._

Examples:

\- The year 1705 does not end in 00, so throw away 17 and keep 05. 05 _is not_
divisible by 4, so 1705 _is not_ a leap year.

\- The year 2000 ends in 00, so throw away 00 and keep 20. 20 _is_ divisible
by 4, so 2000 _is_ a leap year.

The standard method [2] is more complicated:

> Years that are divisible by four are leap years, with the exception of years
> that are divisible by 100, which are not leap years, and with the final
> exception of years divisible by 400, which are.

[1]
[https://twitter.com/jordancurve/status/1012203999716618240](https://twitter.com/jordancurve/status/1012203999716618240)

[2] [https://www.theguardian.com/science/2011/feb/28/leap-year-
al...](https://www.theguardian.com/science/2011/feb/28/leap-year-alex-bellos)

~~~
rovr138
Got tricked during a CS course with this. I bet a lot of the people in that
class will remember the full rule. It then came back on the final.

~~~
bumbledraven
What do you mean, “tricked”? The method is original to me and I don’t think it
has spread very far. Is there a Gregorian calendar year for which the GP
algorithm gives the wrong result?

~~~
htfu
The two methods are exactly - exactly - the same. Just different ways of
phrasing. Don't fool yourself.

~~~
bumbledraven
The standard method and mine give the same result, and I believe that mine is
simpler to carry out in your head.

In what way do you believe that I am fooling myself?

~~~
stinos
Not so much as fooling yourself, but I agree with the OP your method isnt
really 'original' in the sense that it's indeed exactly the same as the
'standard' one, just a tad different in how you _explain_ the math. E.g. 'if
not ending in 00 throw away...' is really just the same thing as 'except when
divisable by 100'.

~~~
jolmg
To add to your comment, being divisable by 400 is also the same thing as
throwing away the 00 and checking the remaining is divisable by 4. One
explanation is just a rephrasing of the other for the exact same method.

------
IgorPartola
If not for religious groups, we could have had World Calendar and all this
would be unnecessary:
[https://en.m.wikipedia.org/wiki/World_Calendar](https://en.m.wikipedia.org/wiki/World_Calendar).

~~~
heyoni
Yea nope. Leap days not having a weekday? How would that even work?

~~~
GavinMcG
Instead of just dumping the first thought that comes through your head on us,
could you explain _why_ you think it wouldn't work? What issues do you see
arising?

It seems to me we go through life with little exceptional circumstances all
the time, and go right back to normal pretty easily.

Is it that hard to imagine having a holiday _not_ disrupting the weekly rhythm
of your life? For example, there's a group I go to every Wednesday. But since
Christmas and New Year's are both Wednesdays, it's being skipped two weeks in
a row. On the other hand, if Christmas and New Year's "didn't count" then we
could carry on without changing the schedule, getting in the way of other
standing plans, etc.

~~~
heyoni
Because that's all I've got and I haven't really given it much more thought
than my initial gut reaction. It just seems infinitely bizarre not to have a
weekday, and writing about it now seems like it would make synchronizing and
automation hell with a day like that.

~~~
Rerarom
There's more to life than synchronizing and automation.

~~~
heyoni
That's the least warranted, holier than though sentence I've ever read here on
HN. I don't even know where to begin to pick this apart. It's not about
enabling automation in the factory making sense, it's about keeping order in
our minds and in our software...and having an "oopsie" blank day with no way
to logically derive will do more to fuck with your intuition about time and
calendars than having everything else around it neatly fit. Even something as
simple as counting days on your hands will become wholly unintuitive because
you now have to consider something worse than an edge-case.

But go ahead, make this about how narrow-minded my view on life is. Arguments
like this are why wishy-washy calendar ideas like the one being proposed got
blown to bits and relegated to a single page wikipedia article barely worth
the occasional mention.

~~~
Rerarom
Come on, I don't disagree with you. But when I was a kid and I first found out
about calendar proposals with blank days it all seemed magical to me and it
just seems weird to me (with regard to this topic) to think about
practicalities.

------
dingaling
This looks like an algorithm that could be useful if programmed rather than
carried around in one's head.

It also still requires a lookup to bootstrap it: the day-of-week of the last
day of February for the selected year. So it's a clever and well-observed
compilation of identified patterns, but not self-contained.

~~~
ikeboy
The version they have here is somewhat inefficient and not well presented.

You can get from the year to the doomsday by a simpler formula:

If odd, add 11; divide by 2; if odd, add 11. Count up to nearest multiple of 7

So e.g. 1955 turns into 66 turns into 33 turns into 44 turns into 5. Add that
to 4 for the century (1900 is 4, 2000 is 3, that's all you really need to
memorize) and you get 9, so the doomsday for 1955 is Monday.

From there it's simple, 4/4 6/6 8/8 10/10 12/12, 9/5 7/11 per the mnemonic
mentioned, last day of February, Jan 3/4 depending on leap year, and March 7
counting forward from February.

There, that's the entire algorithm.

~~~
kseistrup
To go from "any" century, you can also memorize "2053", which is the days in a
4-year cycle: 2000 = 2 = tuesday; 2100 = 0 = sunday; 2200 = 5 = friday; 2300 =
3 = wednesday.

For years other than the centuries, we need to add an offset. Given the year
CCXX, we have:

    
    
        (a, b) = divmod(XX, 12)
        c = b // 4
        offset = a + b + c
        doomsday = start + offset
    

E.g., for 2020 (XX == 20) we get:

    
    
        start = 2  # from the "2053" rule
        (a, b) = divmod(20, 12)  # (1, 8)
        c = b // 4  # 2
        offset = 1 + 8 + 2 = 4 (mod 7)
        doomsday = start + offset  # 2 + 4 = 6 = saturday

~~~
ikeboy
The "add 11" trick in my comment is easier to remember and apply than dividing
by 12 and taking remainders.

~~~
tzs
I like my current method [1], while only requires addition, doubling, and a
couple of conditional increments or additions. Even if you don't bother doing
any mod 7 reduction along the way, you never have to deal with a number above
32.

With both divide by 12 and odd 11, I would find myself occasionally making a
goof when dealing with years near the end of centuries.

[1]
[https://news.ycombinator.com/item?id=21926543](https://news.ycombinator.com/item?id=21926543)

------
hunta2097
My Autistic son does this in a couple of seconds. He can only really do the
last 50 years tho.

Savants who do this are called "human calendars".

~~~
theli0nheart
What method does he use to calculate?

~~~
hunta2097
He can't explain it. AFAIK none of the Human Calendars can, there have been
studies.

I reckon it's memory related, he has an incredible memory and can tell you
everything he did on a specific day in the past!

Maybe at some point he just scanned the Windows calendar or something!? We
(and his teachers) can't work it out.

------
bumbledraven
A simpler and easier way to calculate the day of the week for any date is the
_First Sunday Doomsday algorithm_ :
[http://firstsundaydoomsday.blogspot.com/2009/12/quick-
start-...](http://firstsundaydoomsday.blogspot.com/2009/12/quick-start-
guide.html)

(There’s also a earn-by-example page:
[http://firstsundaydoomsday.blogspot.com/2011/01/learn-by-
exa...](http://firstsundaydoomsday.blogspot.com/2011/01/learn-by-
example.html))

Using Sundays rather than doomsdays simplifies the arithmetic. Another
improvement the above approach incorporates is the odd+11 rule for calculating
the year code.

------
sverhagen
For all but the most basic details my rule is that if I have to remember it,
the system is broken. I know a small handful of passwords off the top of my
head, a few email addresses, my wife's and my phone numbers, and the phone
number of my home during childhood. (I'm obviously exaggerating, you know, for
dramatic effect.) This trick requires so many mnemonic devices that it makes
my head spin. It's still impressive if you can do it. Just not for me.

~~~
netsharc
You only need to remember 5 things:

\- For 2020, the doomsday is Saturday.

All the dates below are doomsdays (So this year they are all Saturdays):

\- 4/4, 6/6, 8/8, 10/10, 12/12, easy enough

\- 9/5, 5/9, 7/11, 11/7 (9-to-5 at 7-11)

\- 0th of March (last day of February)

\- 3rd of January for non-leap years, and 4th of January for leap years. So
this year the 4th is Saturday.

And to calculate dates: mod 7.

So e.g. 7th of July: it's is 4 days before Saturday 7/11, so it's a Tuesday.

~~~
stkdump
You can skip the leap year info completely if you consider both January and
February as belonging to the previous year. That makes sense as the additional
day (Feb 29) is at the end of Februry.

Last year Pi Day was Thursday, this year Saturday.

So the general rule then is: March 14th, April 4th, May 9th, June 6th, July
11th, August 8th, September 5th, October 10th, November 7th, December 12th,
January 2nd, February 6th are Pi Days.

Edit: another nice rule is that usually Pi-Days increase by 1 each year (2 in
leap years), so next year it will be Sunday, then Monday, Tuesday, Thursday
(leap year), Friday, etc.

~~~
netsharc
But why do you call them Pi-Days? Pi Day is 3/14 because that's somewhat
similar to 3.14, which is Pi to 3 significant digits..

~~~
stkdump
They are the same weekday as 3/14 and it makes a little more sense than
'Doomsday', which the article chooses.

~~~
netsharc
I vehemently disagree, you can't just redefine Pi-Day to what you want. Pi Day
is 3/14, not 4/4 or 6/6.

As for calling it Doomsday, well, it's from the title of the paper about the
algorithm, by the man who invented it, the famous John Conway:
[https://en.wikipedia.org/wiki/Doomsday_rule](https://en.wikipedia.org/wiki/Doomsday_rule)

~~~
stkdump
I didn't come up with this. According to the article, Roman Weil of Princeton
teaches the same.

------
sethammons
"[hey seri|ok google|alexa], what day does April 8th fall on?"

------
jb3689
The 4-6-8-... and 9-5-7-11 rules are really nice to have on hand. The rest of
relating years; 99% of the time I'm going to be calculating dates for the
current year so those seem less useful to me (not to mention that part is a
lot more complicated to remember)

------
toolslive
This is how I do it:
[https://incubaid.wordpress.com/category/algorithms/](https://incubaid.wordpress.com/category/algorithms/)

------
cowsandmilk
> There are actually 52 (or 53) other days which are all on the same day of
> the week as "the" Doomsday at the end of February

That seems incorrect, there should always be 51 other days

------
papafox
Doesn't Zellers' Congruence do the same task? Zellers' has been around since
1883, and has been very widely implemented.

------
tzs
Here's a summary of the methods I know for computing the factor based on the
last two digits of the year that gets added to the factor from the century
number to get the Doomsday for the year.

Notation: "A // B" is integer vision (think Python 3 // operator). "A, B = C
/% D" means that "A = C//D" and "B = C % D". "A ≡ B" means A and B are the
same mod 7. "A ≡⁴ B" means A and B are the same mod 4. I'll use x for
multiplication. X + <a,b,c,d> means the four values A+a, X+b, X+c, X+d.

Let Y be the last two digits of the year.

Observation: 365 ≡ 1. If it weren't for leap years, the year factor would
simply go up by 1 each year. A leap year pushes the start of the next year
back a day, and that's cumulative, so we need a correction of the number of
leap years that have past.

1\. That gives the first, and simplest, way to compute the year factor for
year Y.

    
    
      return Y + Y//4
    

Advantage: simplest algorithm.

Disadvantage: numbers get larger than you might be comfortable with for fast
mental meth. Doing 99, for example, gives 99 + 99/4 = 99 + 24 = 123 ≡ 4, which
has plenty of opportunity along the way to goof.

Many people will do better with a method that uses a little more complicated
algorithm but cuts down the size of the numbers.

2\. The divide by 12 method, which is the one given in the article, does this.

    
    
      a, b = Y /% 12
      c = b // 4
      return a + b + c
    

Here's why it works.

    
    
      Y = 12 a + b
      Y//4 = 3 a + b//4
           = 3 a + c
      Y + Y//4 = 15 a + b + c
               ≡ a + b + c
    

Advantage: a <= 8, b < 12, c < 4\. Other than the first /%, you only deal with
fairly small numbers.

Disadvantage: Still easy for many people to goof on the initial /%.

Note: if you divide by 20 instead of 12, you get a similar method, except that
you'll need to use 4a instead of a. Since a is at most 4, 4a is not large. For
many people %/ 20 might be sufficiently easier to deal with in mental math
than %/ 12 that it is worth the cost of having to multiply by 4.

3\. The odd 11 method.

    
    
      Y += 11 if Y is odd
      Y //= 2
      Y += 11 if Y is odd
      return -Y
    

The easiest way to see that this works is to go back to Y + Y//4\. Write Y =
4q + r, where r = 0, 1, 2, or 3.

The first conditional add 11 step turns 4q + <0,1,2,3> into 4q + <0,12,2,14>.
Dividing by 2 then gives 2q + <0,6,1,7>. The second conditional add 11 gives
2q + <0,6,12,18>. Negating mod 7 gives 5q + <0,1,2,3>, which is 4q + <0,1,2,3>
\+ q = Y + Y//4.

Similar considerations give other divide by 2 and negate methods. If you note
that if Y = 4q, then Y + Y//4 ≡ -(Y//2), then it is just a matter of how to
take into account the r in 4q + r when r != 0. One way to do that would be
first subtract r, then do the -(Y//2), and then add r back. That works because
none of the r != 0 years are leap years, and so we just need to add 1 for each
of them.

Another way would be to just go ahead and do -(Y//2), and then add in a
correction based on r. Let Y = 4q + <0,1,2,3>. Then -(Y//2) ≡ 5q +
<0,0,-1,-1>. We want 5q + <0,1,2,3>, so we have to add 0, 1, 3, or 4 if r = 0,
1, 2, 3, respectively.

That last correction can be split into two parts: add 1 if Y is odd, plus add
2 if Y//2 is odd. That gives:

    
    
      t = Y odd ? 1 : 0
      Y //= 2
      t += 3 if Y is odd
      return -Y + t
    

4\. The method I actually use, which views the two digit year as a decade part
and a year within the decade part, and operates on them separately. Since I
gave a long description of it yesterday, I'll just link to that [1] here.

[1]
[https://news.ycombinator.com/item?id=21926543](https://news.ycombinator.com/item?id=21926543)

------
bubba1236
this is a great article went through it and can do it now

------
kissgyorgy
It's a nice article and a good algorithm, kudos to all who can do this.

My philosophy however is that I don't need to learn this kind of stuff
nowadays. There are computers even in our wrist, so I offload as much as I
can, and spare my brain cycles more important stuff that matters.

