Dates That Don't Exist (2015)
摘要
A blog post exploring the nonexistent dates of October 5-14, 1582 due to the Gregorian calendar reform, and how Ruby, Python, and Perl handle these invalid dates.
暂无内容
查看缓存全文
缓存时间: 2026/08/04 16:46
# Mini-post: Dates That Don't Exist
Source: [https://blog.yossarian.net/2015/06/09/Dates-That-Dont-Exist](https://blog.yossarian.net/2015/06/09/Dates-That-Dont-Exist)
## ENOSUCHBLOG
## *Programming, philosophy, pedaling\.*
- [Home](https://blog.yossarian.net/)
- [Tags](https://blog.yossarian.net/tags)
- [Series](https://blog.yossarian.net/series)
- [Favorites](https://blog.yossarian.net/favorites)
- [Archive](https://blog.yossarian.net/archive)
- [Main Site](https://yossarian.net/)
- [TILs](https://yossarian.net/til)
---
## *Jun 9, 2015*Tags:[programming](https://blog.yossarian.net/tags#programming)
This post is at least a year old\.
### Calendars and Missing Dates[\#](https://blog.yossarian.net/2015/06/09/Dates-That-Dont-Exist#calendars-and-missing-dates)
In 1582, under the*[inter gravissimas](http://www.bluewaterarts.com/calendar/NewInterGravissimas.htm)*papal bull, the Catholic world transitioned from the[Julian Calendar](https://en.wikipedia.org/wiki/Julian_calendar)to the[Gregorian Calendar](https://en.wikipedia.org/wiki/Gregorian_calendar)\. This new calendar shortened the length of the year from`365\.25`days to`365\.2425`, a reduction of just`0\.002%`\.
One side effect of this is the modern leap year system, in which every fourth and 400th year is a leap year, but no other year divisible by 100 is\. For example, this means that 1900 was a normal year, 1904 was a leap year, and 2000 was also a leap year\.
Another side effect \(and the topic of today’s post\) was that the Julian and Gregorian calendars no longer agreed on the date\. Calculating each from 1 to to 1582 AD, the Julian calendar had slowly accumulated “drift” relative to the Gregorian calendar, lagging eleven days behind it\.
To correct for this drift, ten days had to be removed from the 1582 year, converting the entire system from Julian to Gregorian\. Selecting an appropriate 10\-day span took nearly 20 years \(owing in no small part to the Catholic church’s reluctance to skip any holidays and desire to correct the Easter drift\), 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\*went to sleep and woke up ten days later, on the fifteenth of October, with a new calendar\.
In essence, then, those ten days in 1582**never happened**and simply**do not exist**within the Gregorian calendar system used almost universally in the West today\.
So, how well do programming languages handle this range of dates?
#### Ruby[\#](https://blog.yossarian.net/2015/06/09/Dates-That-Dont-Exist#ruby)
Right off the bat, Ruby does the right thing \- it simply does not allow a`DateTime`with an impossible Gregorian date to be created:
```
1
2
3
4
5
6
7
irb(main):001:0> require 'date'
=> true
irb(main):002:0> DateTime.new(1582, 10, 5) # October 5, 1582
ArgumentError: invalid date
from (irb):2:in `new'
from (irb):2
from /usr/bin/irb:12:in `<main>'
```
This can be traced to the`datetime\_s\_civil`function in*ext/date/date\_core\.c*:
```
1
2
3
4
if (!valid_gregorian_p(y, m, d,
&nth, &ry,
&rm, &rd))
rb_raise(rb_eArgError, "invalid date");
```
#### Python[\#](https://blog.yossarian.net/2015/06/09/Dates-That-Dont-Exist#python)
Python’s`datetime`module, despite claiming to represent a`date`object in “the current Gregorian calendar,” sadly does not do so:
```
1
2
3
4
5
6
7
8
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import date
>>> date(1582, 10, 5) # October 5, 1582
datetime.date(1582, 10, 5)
>>> date(1582, 10, 5).ctime() # October 5, 1582
'Tue Oct 5 00:00:00 1582'
```
This is the case for both Python 2 and Python 3\.
#### Perl[\#](https://blog.yossarian.net/2015/06/09/Dates-That-Dont-Exist#perl)
Perl has no standard analog to Ruby’s`DateTime`or Python’s`date`, so I opted for the common[`DateTime`module](https://metacpan.org/pod/DateTime)from the CPAN instead\. Unfortunately, like Python, a proper error message for impossible Gregorian dates is notably absent:
```
1
2
3
4
5
6
7
#!/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 1\.19\.
### Summary[\#](https://blog.yossarian.net/2015/06/09/Dates-That-Dont-Exist#summary)
Despite the fact that dates between the 5th and 14th of October in 1582 are impossible to represent on the Gregorian calendar, two out of the three languages 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 far we’ve come with respect to plain and simple**correctness**in date and time implementations\. Even if it means adding an extra check to make sure that 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 intricacies\. If you’re still interested, there are a ton of cool mathematical formulas and historical justifications for the current calendar system \([Zeller’s Congruence](https://en.wikipedia.org/wiki/Zeller%27s_congruence),[Pre\-Julian Calendars](https://en.wikipedia.org/wiki/Roman_calendar)\) worth taking a look at\.
Happy Hacking\!
\- William
**Afternotes**:
\* As one might suspect, the non\-Catholic churches \(and religions\) were less than inclined to obey an official papal bull\. As a result, although the**“official”**calendar reform took place in the October of 1582, many protestant churches continued to use the Julian calendar well into the 18th century\. The Eastern Orthodox church even continued well after that, only switching to the Gregorian calendar in 1929\. These later switches required their own 10\+ day removals in order to synchronize the Julian and Gregorian calendars\.
*P\.S\.*:
On a whim, I checked`ncal\(1\)`’s Gregorian correctness\. Interestingly enough, it may be the most correct of all\. Instead of assuming that the Catholic adjustment is the most correct one, it takes a country code with the`\-s`flag and attempts to determine when that country performed their adjustment\.
For example, Italy \(`ncal \-s IT 10 1582`\):
```
1
2
3
4
5
6
7
8
October 1582
Su 17 24 31
Mo 1 18 25
Tu 2 19 26
We 3 20 27
Th 4 21 28
Fr 15 22 29
Sa 16 23 30
```
…and Great Britain \(`ncal \-s GB 9 1752`\):
```
1
2
3
4
5
6
7
8
September 1752
Su 17 24
Mo 18 25
Tu 1 19 26
We 2 20 27
Th 14 21 28
Fr 15 22 29
Sa 16 23 30
```
Although this likely takes a great deal of work, it’s by far the most**correct**of all\.
**Addendum 2026\-06\-30**:[John Costello](https://joxn.org/)points out that`ncal\(1\)`is still not perfectly correct, since it misses Sweden’s calendar shifts in the 1700s\. Here’s a[verbatim Gist](https://gist.github.com/woodruffw/bb056927958d7593793e9613bb810eb6)of his analysis; thanks John\!
---
相似文章
公元零年二月的一个错误
PHP 的 DateTimeImmutable 中一个罕见的错误导致公元零年二月出现日期偏差一天的问题;解决方法是使用替代的时间戳转换方法。
重访天数计算
Tony Finch 重新审视了他的格里高利历到儒略历天数转换算法,融合了 Ben Joffe 的技巧,得出了一个更高效、更稳健的公式。
JavaScript的诞生与消亡(2014)
Gary Bernhardt在PyCon 2014上的一场演讲,幽默地追溯了JavaScript从1995年到2035年的历史与未来,讨论了其缺陷与积极影响。
@freeCodeCamp: 互联网技术标准有着出人意料的悠久愚人节玩笑历史。在这篇文章中,Omer 趣味讲述…
本文探讨了 IETF 在愚人节发布幽默 RFC 的传统,涵盖了诸如用信鸽传输 IP、邪恶位和 HTTP 418 等著名玩笑。
C语言中在C++中仍然无法工作的构造——以及一些已发生变化的构造
一篇更新经典调查的博文,关于C语言中在C++中无法工作的构造,涵盖了C++20和C23标准中影响兼容性的变化。