Shane and I were busy this past summer May – August co-hosting our interns Andrew and Pedro, who worked hard on implementing more calendar systems in ICU4X. In the icu::calendar crate, they added the modules chinese, dangi (Korean), hebrew, islamic (includes civil, observational, tabular, and Umm-al-Qura), persian, and roc (Taiwan). The summer required us all learning a lot about calendar systems, and how dates and times are just smaller units of the larger calendar systems. Humans created those calendar systems to precisely calculate the mathematically messy phenomena we use to orient our lives: the spin of the Earth, the orbit of the moon, and the orbit of Earth. It turns out there is one book that authoritatively catalogs all human calendar systems. The following are short videos giving an introduction to what makes calendars interesting, and a properly working version of the code for the Calendrical Calculations book.
Short videos on times, dates, and calendar systems
The word “time” has a few meanings, but in the sense of “what time is it?”, it’s a reference to a point in time within a day. But what is a day? When does it start? When does it end? (Doesn’t a day end when the next one begins?)
Okay, so time is a little funny because a day is not perfectly 24 x 60 x 60 seconds long. It depends on how fast the Earth spins, which changes over time. Now, the same goes for a month, and a year. A calendar system is an attempt to bring order to something that is inherently messy, and that’s how we get so many around the world:
If calendars aren’t tricky enough, calendars also get changed due to political and/or religious purposes. This comedian had a whole bit about Gregorian calendar wackiness and suggested an alternative based on an idea that had been proposed in history. But the history of such wackiness is even more surprising than the jokes themselves, and there are modern day examples of the same things still occurring.
When it comes to types of calendar systems (how they define a year), the most common are solar, lunar, and sidereal. Solar calendars define a year as the time it takes for the sun to return to the same position in the sky. Lunar calendars define a year by the time for certain number of month cycles to elapse (12 month cycles in a normal lunar year, or 13 month cycles in a lunar leap year). Sidereal calendar define a year as the amount of time that it takes for the stars to match their exact position in the sky again. Long after doing all of this work, here’s what I only recently found out: a sidereal year (which defines a day by star position, and thus is a little shorter than 24 hours) has exactly 1 more day than a solar year (which defines a day by sun position). And when you see this video, which starts off talking about an SAT math problem that everyone got wrong (including the test writers), you will eventually see how it all nicely explains sidereal calendars vs. solar calendars, with great graphics, too:
Working code for Calendrical Calculations book
There is one book that is the authoritative reference for all calendar systems around the world. It’s called Calendrical Calculations by Cambridge University Press. It’s nicely written, in that it is fairly concise, and it includes bits of history and pictures where relevant. The describe the algorithms to do each calendar’s calculations, and they simplified them when possible. Importantly, they wrote code to implement all of those algorithms.
Thanks to our former product manager teammate in Google’s Internationalization group’s libraries team, Luke, the authors released their code on Github under a permissive open source license. Luke spent more than a year talking to the publisher and the authors to explain the importance of the code, open source code, licenses, Github, etc. Since the first edition, the book included several pages of the printed version of the source code written by the authors, which is a practice held until the 1980s and serves no purpose these days. You know, to give readers your code, we now have floppy disks, CD-ROMs, USB drives, and… the internet.
As it turns out, once the authors published their code on Github, people started trying to use it. And as good as the code is, others were not able to get the code to compile as it was uploaded. For Pedro and Andrew’s work to implement those algorithms in Rust for ICU4X, they needed the original code to debug their new code, and to verify that their new code is giving the correct results. You can’t even write unit tests without knowing the correct expected values, and writing code without test cases is no way to go about programming.
Ultimately, what I had to do is port the Common Lisp code from the book into Clojure, a modern Lisp that runs on the JVM. Doing so allows executing the code easy, and it will also be very straightforward for others to get setup and execute the code themselves. I had to do a lot of cleanup, too, like reordering functions and making forward declarations because the original code was using functions that hadn’t yet been defined. My resulting code is in my fork of the repo, at:
https://github.com/echeran/calendar-code2
Enjoy! Open an issue if notice bugs. I’ll open a Pull Request on the original upstream repo to see if I can get my Readme and Clojure port merged in.