When dating goes too far

Yep, we’re talking about the leap year! With 29 February coming up, we look at leap years, leap seconds and other date rollover issues that require complex programming solutions.

Although it’s been a good two decades, many devs will remember well the Y2K problem or the Millennium bug.

In the early days of the year 2000, many programs could not distinguish the new year from the year 1900 because their code represented years with just two digits – MMDDYY.

The compact MMDDYY format had been helpful in reducing file sizes and database storage but, in retrospect, created tough problems for some critical infrastructure. 

Leap years 

In comparison, leap years are less problematic. For starters, they happen much more often than new millennia, so the problems with them are better documented. Yet, leap year bugs exist and there have been several high-profile cases including the Microsoft Azure cloud outage

We add an extra day every four years to keep in sync with the Earth’s rotations around the sun. Without 29 February, in 100 years the calendar would be off by 24 days. 

To work out if a year is a leap year, devs can perform a modulo operation

Leap years can also wreak havoc on December 31, because it is the 366th day of the year and many applications mistakenly hard-code a year as 365 days.

But as long as devs don’t try to implement their own date logic, most code should be leap year-proof. 

Leap seconds

Leap seconds are much more disruptive and difficult to handle, especially when it comes to services that depend on precise time stamping.

These one-second adjustments are applied to UTC, the reference for civil time in most countries, to accommodate the difference between the precise “atomic time” and the imprecise solar time. The imprecise solar time – known as UT1 – varies due to a general slow-down in the Earth’s rotation. 

UTC needs the occasional leap second to reset it to UT1 but that’s rather irregular and unpredictable. It’s usually decided six months in advance by the International Earth Rotation and Reference Systems Service

The last reset took place on December 31, 2016, at 18:59:60 ETC. The IERS is looking into abolishing the practice. 

Y2K38

Many digital systems represent time as the number of seconds passed since 00:00:00 UTC on 1 January 1970. They store it as a signed 32-bit integer (a so-called “Unix Timestamp”). 

These systems will get stuck at 03:14:07 UTC on 19 January 2038 because this is the latest time that can be stored using a signed 32-bit integer (2,147,483,647 seconds after 1 January 1970). 

At that point, Unix machines will run out of the bits to tick off seconds and programs will start having problems with dates. 

Y2K38 will affect embedded systems that rely on storing accurate time and date – transportation systems, as well as communication systems on mobile phones, routers, and wireless access points. 

Programs that work with future dates will begin to run into problems sooner, e.g. if a program works with dates 10 years from now, it will need to be fixed in January 2028.

At the moment, there’s no universal solution for the Year 2038 bug but work is being done to fix it in Linux.  

Network Time Protocol 

The NTP will hit a similar roadblock in 2036. 

NTP uses 64-bit timestamps which consist of 32 bits for second and 32 bits for the fractional second, giving NTP a time scale that rolls over every 136 years. Since NTP uses an epoch of 1 January 1900, the first rollover will happen in 2036.

It’s advised that devs disambiguate NTP time using a knowledge of the approximate time from other sources. For example, many systems use a battery-powered hardware clock to avoid this problem.

Should errors occur, clients will receive the date as 1900-01-01 00:00:00UTC, not 2036-02-07 06:28:15.

Many embedded systems won’t be able to store this time in Unix format because Unix time starts on 13 December 1901 (signed 32 bit integer) or 1 January 1970 (unsigned 32 bit integer).

Future versions of NTP may extend the time representation to 128 bits: 64 bits for the second and 64 bits for the fractional-second. 

* * *

Most programming languages already have pre-written libraries that deal with the many complications of handling dates and times, and using these will save you dealing with the many edge cases that you haven’t thought of.

And before you go, do take a look at this well-known cautionary tale about dealing with time and timezones. 🤦🤦‍♀️

Oh, and any leaplings out there?

Thanks to @thomasp for his contribution to this blog post.