Monday, October 3, 2011

Why make it complicated when you can make it impossible?

Dates and times may be quite familiar but when you need to do something with them, especially in software, you are confronted with a glorious mess. To get an idea, spend a few moments on the subject in Wikipedia, Google, or the Java documentation. Here are some of the things you will find.

There is no year zero, except when there is one...

If you are a historian, there is no year 0. The year AD 1 immediately follows the year 1 BC (see Anno Domini in Wikipedia). On the other hand, if you are an astronomer, there is a year 0 (see Astronomical year numbering in Wikipedia). In the ISO 8601 international standard for representing dates and times, years are represented by four digits from 0000 to 9999. So, if you are following the standard, there is a year 0. But with XML, there is a problem. XML time was inspired by an early version of ISO 8601 and disallows year 0. Fortunately, this is likely to change in the future to agree with more recent versions of ISO 8601. See XML Schema Part 2: Datatypes Second Edition from W3C.

If you have an ancestor born on October 10, 1582, stick to the ISO standard!

In some countries, October 15, 1582 immediately followed October 4 (see Gregorian calendar in Wikipedia). The ISO 8601 international standard states that every date must be consecutive and that dates before October 15 1582 can be used by mutual agreement when exchanging information. So, under the standard, there would have been no hole between October 4 and 15, 1582, and your ancestor would have been born on an existing day.

Some minutes have 61 seconds

Nowadays, time is measured with atomic clocks (see Coordinated Universal Time (UTC) in Wikipedia). Atomic time does not exactly match the earth's rotation and a so-called leap second can be added or substracted from UTC at the end of June or December to avoid the discrepancy growing beyond a second. So, minutes have 59, 60, or 61 seconds. For more information on leap seconds, consult Date and Time on the Internet: Timestamps (RFC3339) at the IETF, and Leap Seconds at the US Naval Observatory. Note because it is not known long in advance when one will be introduced, leap seconds cannot be programmed in software.

Avoid the Dutch calendar between 1909 and 1937

When using local time, time zones and daylight savings time are issues to consider. The fact that most methods of the Java Date class are deprecated shows that getting such things right is not straightforward. Calendar and Joda Time are better, but their complexity can be seen as further proof that dates and times are messy. The ISO 8601 standard attempts to sidestep the whole question by not supporting time zones at all. Time is either local or expressed as an offset from UTC. But even then, there is a problem. The offset used by the ISO standard is in hours and minutes. But there are known cases where this is not sufficient. Here is a quote from RFC 3339:

1937-01-01T12:00:27.87+00:20

This represents the same instant of time as noon, January 1, 1937,
Netherlands time. Standard time in the Netherlands was exactly 19
minutes and 32.13 seconds ahead of UTC by law from 1909-05-01 through
1937-06-30. This time zone cannot be represented exactly using the
HH:MM format, and this timestamp uses the closest representable UTC
offset.

The Y2.038K problem

If you thought the year 2000 problem was interesting, then you will like 2038, when the Unix clock will wrap around. Such problems and many facts about dates and times are documented in Gilbert Healton's The Best of Dates, The Worst Of Dates.

Time and the Time2 Library

When I wrote the Time2 Library, I was looking for something lightweight to represent dates and the time of day. Dates and times are only a small part of what the library does and I did not want to spend too much time on time. But I was not happy with Java's Date because it is mostly deprecated. Other possible solutions were not exactly lightweight. So I decided to write my own solution and to keep it simple, with the requirement to implement part of the ISO 8601 specification (ignoring durations and intervals): all years between 0000 and 9999 valid, no hole in October 1582, no support for time zones and daylight savings time, but tolerance for time zone offsets and leap seconds (the last two things are still on the to-do list.)

No comments:

Post a Comment