Zhu Wu's Blog

The world is a fine place and worth fighting for.

Handle Historical Date in Java

As a Java programmer, you might have used Java Calendar class for thousands of times. Most likely you have a good knowledge on how to handle modern dates, but this blog will provide you more insights on how to use GregorianCalendar class to handle historical dates.

Before jump into technical details, we need some basic knowledge on Julian calendar and Gregorian calendar first. The Julian calendar, which is introduced by Julius Caesar in 46 BC, took effect in 45 BC. It divides one year into 12 months, and the length of each month is shown in the table below:

Month Number of days
January 31
February 28 (leap years: 29)
March 31
April 30
May 31
June 30
July 31
August 31
September 30
October 31
November 30
December 31

Unfortunately, leap year error was introduced after the adoption of Julian Calendar: the leap day was added every three years instead of four, and the error lasted for 36 years. As a result, 12 leap days were inserted instead of 9. Augustus corrected the error by skipping leap day in the following 12 years, and then started to insert leap day every 4 years in the correct way. It was a chaotic period and we do not know how the leap days were applied in the first 36 years. Scholars have had different ideas on how the leap days were inserted before 8 AD, and you can refer to Leap Year Error for the schemes proposed by scholars.

Gregorian calendar was introduced in 1582 as a refinement to Julian calendar by Pope Gregory XIII. Gregorian calendar adds leap day every year which is exactly divisible by 4, except for years that are exactly divisible by 100, but these centurial years are leap years if they are exactly divisible by 400. Moreover, as error accumulated during years, Julian calendar was ten days out of alignment in 1582. Thus, when Catholic countries adopted Gregorian calendar in 1582, Julian calendar day Thursday, 4 October 1582 was followed by the first day of the Gregorian calendar, Friday, 15 October 1582. Protestant countries, Orthodox countries and some other countries switched from Julian calendar to Gregorian calendar later, so they had different adjustment on date. For example, Britain adopted Gregorian calendar in 1752, Julian calendar day Wednesday, 2 September 1752 was followed by Thursday, 14 September 1752.

Since we have some basic knowledge on calendar history already, let's discover the Java implementation of GregorianCalendar class. GregorianCalendar class in Java is hybrid calendar that supports both the Julian and Gregorian calendar. The default starting day of Gregorian calendar in GregorianCalendar class is 15 October 1582, and you are able to change it by calling setGregorianChange method. GregorianCalendar class implements Julian calendar before the Gregorian calendar cutover. Julian calendar in GregorianCalendar class always adds leap day when year is divisible by 4 and it does not deal with leap year error before 8 AD. GregorianCalendar class can compute dates by extrapolating current rules indefinitely far backward and forward in time. However, dates obtained using GregorianCalendar class are historically accurate only from March 1, 4 AD onward due to the leap year error (it can be deducted by a simple calculation: 45BC + 36 years + 12 years = 4AD).

Here are some references if you want to explore more details: