Mini-post: Dates That Don't Exist
ENOSUCHBLOG
Programming, philosophy, pedaling.
Home
Tags
Series
Favorites
Archive
Main Site
TILs
Mini-post: Dates That Don't Exist
Jun 9, 2015
Tags:
programming
This post is at least a year old.
Calendars and Missing Dates#
In 1582, under the inter gravissimas<br>papal bull, the Catholic world transitioned from the<br>Julian Calendar<br>to the Gregorian Calendar.<br>This new calendar shortened the length of the year from 365.25 days to<br>365.2425, a reduction of just 0.002%.
One side effect of this is the modern leap year system, in which every fourth<br>and 400th year is a leap year, but no other year divisible by 100 is. For<br>example, this means that 1900 was a normal year, 1904 was a leap year, and 2000<br>was also a leap year.
Another side effect (and the topic of today’s post) was that the Julian and<br>Gregorian calendars no longer agreed on the date. Calculating each from 1 to<br>to 1582 AD, the Julian calendar had slowly accumulated “drift” relative to the<br>Gregorian calendar, lagging eleven days behind it.
To correct for this drift, ten days had to be removed from the 1582 year,<br>converting the entire system from Julian to Gregorian. Selecting an appropriate<br>10-day span took nearly 20 years (owing in no small part to the Catholic<br>church’s reluctance to skip any holidays and desire to correct the Easter drift),<br>but eventually the span of October 5 to October 14 was chosen.
The end result? On the fourth of October, 1582, citizens of the Catholic world*<br>went to sleep and woke up ten days later, on the fifteenth of October, with a<br>new calendar.
In essence, then, those ten days in 1582 never happened and simply do not<br>exist within the Gregorian calendar system used almost universally in the West<br>today.
So, how well do programming languages handle this range of dates?
Ruby#
Right off the bat, Ruby does the right thing - it simply does not allow a<br>DateTime with an impossible Gregorian date to be created:
irb(main):001:0> require 'date'<br>=> true<br>irb(main):002:0> DateTime.new(1582, 10, 5) # October 5, 1582<br>ArgumentError: invalid date<br>from (irb):2:in `new'<br>from (irb):2<br>from /usr/bin/irb:12:in `'
This can be traced to the datetime_s_civil function in ext/date/date_core.c:
if (!valid_gregorian_p(y, m, d,<br>&nth, &ry,<br>&rm, &rd))<br>rb_raise(rb_eArgError, "invalid date");
Python#
Python’s datetime module, despite claiming to represent a date object in<br>“the current Gregorian calendar,” sadly does not do so:
Python 2.7.6 (default, Mar 22 2014, 22:59:56)<br>[GCC 4.8.2] on linux2<br>Type "help", "copyright", "credits" or "license" for more information.<br>>>> from datetime import date<br>>>> date(1582, 10, 5) # October 5, 1582<br>datetime.date(1582, 10, 5)<br>>>> date(1582, 10, 5).ctime() # October 5, 1582<br>'Tue Oct 5 00:00:00 1582'
This is the case for both Python 2 and Python 3.
Perl#
Perl has no standard analog to Ruby’s DateTime or Python’s date, so I opted<br>for the common DateTime module from the<br>CPAN instead. Unfortunately, like Python, a proper error message for impossible<br>Gregorian dates is notably absent:
#!/usr/bin/env perl
use DateTime;
my $dt = DateTime->new(year => 1582, month => 10, day => 5);
print $dt->ymd('/'), "\n"
This example runs without error (which is the error) on Perl 5.18, with DateTime<br>1.19.
Summary#
Despite the fact that dates between the 5th and 14th of October in 1582 are<br>impossible to represent on the Gregorian calendar, two out of the three languages<br>tested allow programmers to create “Gregorian” dates for those days.
This is certainly no Y2K or Unix epoch problem, but it’s a good indicator of how<br>far we’ve come with respect to plain and simple correctness in date and time<br>implementations. Even if it means adding an extra check to make sure that<br>nobody creates a date within a 10-day range nearly 500 years ago.
I hope you’ve enjoyed this quick little exploration into calendars and their<br>intricacies. If you’re still interested, there are a ton of cool mathematical<br>formulas and historical justifications for the current calendar system<br>(Zeller’s Congruence,<br>Pre-Julian Calendars) worth<br>taking a look at.
Happy Hacking!
- William
Afternotes :
* As one might suspect, the non-Catholic churches (and religions) were less<br>than inclined to obey an official papal bull. As a result, although the<br>“official” calendar reform took place in the October of 1582, many protestant<br>churches continued to use the Julian calendar well into the 18th century. The<br>Eastern Orthodox church even continued well after that, only switching to the<br>Gregorian calendar in 1929. These later switches required their own 10+ day<br>removals in order to synchronize the Julian and Gregorian calendars.
P.S.:
On a whim, I checked ncal(1)’s Gregorian correctness. Interestingly enough,<br>it may be the most correct of all. Instead of assuming that the Catholic<br>adjustment is the most correct one, it takes a country code with the -s flag<br>and attempts to determine when that country performed their adjustment.
For...