Tuesday, October 8, 2013

Calculating the next Thanksgivukkah with remind

Apparently, this year will see a rare coincidence of Thanksgiving with the first day of Hanukkah. It has been reported that this will not occur again for 79,043 years. I was suspicious of this and wanted to find for myself when the next Thanksgivukkah might occur. Now, this is a fairly complicated prospect as Thanksgiving (in the US) is defined as the last Thursday of November, while Hanukkah begins on the 25th of Kislev on the lunisolar Hebrew calendar. It turns out that there are some very powerful free software tools for GNU/Linux for calculating dates which can handle even this kind of complicated question.

I used a handy tool called remind. I'm sure you could do the same thing with Emacs calendar. (Actually by the time I was done, I was thinking I really should have tried Emacs instead...) With remind you store your reminders in a specially formatted text file. It is a command-line tool with many options and gui frontends available, but here I will just illustrate using the command-line tool to calculate the next date of Thanksgivukkah.

First, let's look at how to individually find the dates of Thanksgiving and Hanukkah. Here is what we need to set a reminder for Thanksgiving:

REM Nov Thurs 22 MSG Thanksgiving

This reminder will be triggered on the first Thursday on or after the 22nd of November, which is always the fourth Thursday.

Now, for Hanukkah remind thankfully supplies functions to support the Hebrew calendar, so here is what we will use for Hanukkah:

REM [trigger(hebdate(25, "Kislev"))] MSG Hanukkah

So remind calculates what day the 25th of Kislev falls on in our Gregorian calendar and all is right with the world. So how do we find when the two fall on the same day? This is where it gets complicated. First, we need to write a user-defined function that will check whether a date is Hanukkah:

FSET isHanukkah(date) \
     trigger(date) == trigger(hebdate(25, "Kislev", trigdate()))


This function compares the current date being evaluated with the date of Hanukkah for that year. Now, we will use the SATISFY clause to search for a Thanksgiving that is also Hanukkah and print a reminder:

REM Nov Thurs 22 SATISFY [isHanukkah(trigdate())] MSG Thanksgivukkah

So, to look just for the next date of Thanksgivukkah, create a remind file that contains only:

FSET isHanukkah(date) \
     trigger(date) == trigger(hebdate(25, "Kislev", trigdate()))
REM Nov Thurs 22 SATISFY [isHanukkah(trigdate())] MSG Thanksgivukkah

Now, in the process of writing this I discovered that in order to get this to work, you need a 64-bit system, and you need to recompile remind to take advantage of the larger dates a 64-bit signed integer can handle, otherwise you just get a date overflow error. (When I initially had used the pre-1942 definition of Thanksgiving, I did not run into this problem, see the note at the end. But since I had already published the mistake, I shall show the correct way even if we must edit and recompile from source. Onward!)

If you are brave enough to proceed with compiling your own modified remind (and have a 64-bit system), once you have downloaded the source and unpacked it, you will need to edit config.h.in and change

#define YR_RANGE 4000

to

#define YR_RANGE 17536635926176

To compile, just run:

wish ./build.tk

If you wish to install it system-wide, just do:

make install

Now, you can set you system clock to some time after Thanksgivukkah this year and print the next date with:

remind -n -x77030 /path/to/Thanksgivukkah-reminder-file

You can avoid the silliness with (falsely) resetting the system clock by printing a list of dates, but this performs very poorly and may take hours to run:

remind -s853000 -x77030 /path/to/Thanksgivukkah-reminder-file

 (Note that -xn sets how many times the SATISFY clause will be evaluated and the default is only 150)

Either way, we can confirm that the next date of Thanksgivukkah is November 23, 79043. So it's not quite 79,043 years in the future, but actually the year 79043.

EDIT

I initially used the pre-1942 definition of Thanksgiving, which was the last Thursday of November, rather than the fourth Thursday of November. For that we use:

REM Dec Thurs 1 -7 MSG Thanksgiving

Now I bet you are thinking that looks mighty odd, especially since Thanksgiving is in November, not December. It is not a typo, what we are doing here is to find the first Thursday in December and then counting back 7 days to get to the last Thursday in November.

So in this case we would use:

FSET isHanukkah(date) \
     trigger(date) == trigger(hebdate(25, "Kislev", trigdate()))
REM Dec Thurs 1 -7 SATISFY [isHanukkah(trigdate())] MSG Thanksgivukkah

If you didn't proceed with the recompilation described above, this example should still work fine for you, just run:

remind -s2965 -x247 /path/to/Thanksgivukkah-reminder-file

Now, the answer we get is:

2013/11/28 * * * * Thanksgivukkah
2108/11/29 * * * * Thanksgivukkah

2260/11/29 * * * * Thanksgivukkah

So the next date of Thanksgivukkah would only be 95 years away, on November 29, 2108, if we still celebrated Thanksgiving on the traditional date of the last Thursday of November. So, if you really want more Thanksgivukkah, you should petition Congress to change the date of Thanksgiving back! (Although this really only gives you two more Thanksgivukkahs before Hanukkah drifts away from Thanksgiving for millennia.)

It is also noteworthy that there will be a few more instances when Thanksgiving coincides with the first night of Hanukkah. That is, the first candle will be lit on the evening of Thanksgiving, but it won't technically be Hanukkah until sunset on Thanksgiving evening. We can find these dates simply by using the 24th of Kislev instead of the 25th, and this is another example you can run without modifying remind. This will give us:

2070/11/27 * * * * Thanksgivukkah?
2165/11/28 * * * * Thanksgivukkah?


Well, that's kind of like Thanksgivukkah, I suppose.