Programming "time": why it's so difficult to work with dates and times in software development
Apr 27, 2024
7 min read
Okay, raise your hand if you ever had a bug related to dates and times in your code. 🙋♂️
You raised your hand, right? Don't worry, me too. And I'm pretty sure that almost every developer has already faced this kind of problem at least once in their career. But why is it so difficult to work with dates and times in software development? Why do we have so many problems with them? Today I'll show you some curiosities about time and dates that you probably didn't know. So, let's get started!
Assume that what you know about time is wrong
I'm sure you have had to manipulate dates and times in your code at some point. Something as simple as adding a number of days to a date, to set the expiration of an API token, for example.
Let's say you want to create a token that expires after one year. Although is not recommended to use such a long expiration time, let ignore the security implications, as I want to focus only in the date manipulation. You might be tempted to do something like this:
from datetime import datetime, timedelta
current_date = datetime.now()
expiration_date = current_date + timedelta(days=365)
print(expiration_date)
I'm sorry to tell you that, if you are doing things that way, you are introducing a bug in your code. Why? Because you are assuming that a year has always 365 days.
If I execute the code above today, April 27, 2024, the expiration date will be April 27, 2025. But if I executed the same code the past year, the expiration date would be April 26, 2024. Why? Because 2024 is a leap year, so February had 29 days. Therefore, if you add 365 days to a date that is in a leap year, you will end up with a date that is one day before the expected date.
This might seem like a silly example, and you might be thinking "This doesn't happen in the real world. Any programmer will just add 1 year instead of 365 days to ensure the time library being used takes care of that".
Oh, really? Have you ever heard about leap day bugs? There are many examples of software that had bugs related to leap days. There are even people listing them on the internet. For example, Gergely Orosz did so in The Pragmatic Engineer, and also, Matt Johnson-Pint has been recording leap day bugs for three different leap years.
Just to name a few striking examples this year:
- The biggest airline in Colombia, Avianca, printed tickets for February 29, 2024, with the incorrect date of March 1, 2024.
- Some EA multiplayer videogames could not be played if the player system date was set to February 29, 2024. A workaround to play that day was to set the system date to March 1, 2024.
- Several payment terminals across the globe stopped to work on February 29, 2024.
So did you said that that doesn't happen in the real world? That is not a valid argument. It happens, and it happens more that we would like to admit.
Not, really, assume that what you know about time is wrong
"Okay, it happens, but time normally behaves in the same way, those are just some minor exceptions I already know."_ you might be thinking now. Let me ask you: what are those exceptions? You are probably thinking the already mentioned lap years, and also the summer time changes (some countries change the time twice a year, moving the clock one hour forward or backward). Is that all? What if I tell you that the following is true:
- A day can have 30 hours.
- The day after a Thursday is not always a Friday.
- Not all leap years occur every 4 years.
- Timezones shifts can be greater than +12 hours or lower than -12 hours.
And there are a lot more. So please, if you want to become a better programmer, assume that what you know about time is wrong, and take special care when working with dates and times in your code. Always use battle-tested time manipulation libraries, and always test your code with different dates and times.
Now, let me explain the four examples I gave you:
A day can have 30 hours
In Japan, times past midnight can also be counted past the 24 hour mark, usually when an associated activity spans across midnight. For example, bars or clubs may advertise as being open until "30時" (i.e. 6 am). This is a cultural thing in Japan, partly because the closing time is considered part of the previous business day.
The day after a Thursday is not always a Friday
On the last week of December 2011, the Samoan government decided to skip December 30, 2011, and move directly to December 31, 2011 from December 29, 2011. This was done to align the country's calendar with its main trading partners, Australia and New Zealand. That means, people at Samoa went to bed on Thursday, and wake up next day on Saturday. They had not Friday that week.
Not all leap years occur every 4 years
Okay, this is a tricky one. The Gregorian calendar has a leap year every 4 years. That effectively means, that every year divisible by 4 will be a leap year, right? Like 2024, 2028... 2100? No, because there are exceptions. For example, the year 2000 was a leap year, but the year 1900 was not. Also, the year 2100 won't be a lap year neither. This is because the Gregorian calendar has a rule that states that years that are divisible by 100 are not leap years, unless they are also divisible by 400.
That's because a year is not exactly 365.25 days long, but 365.2425 days long. So, if we don't correct this, we would have an error of 0.75 days every 100 years (about 3 extra leap days in 400 years). By ensuring only century years divisible by 400 are leap years, we correct this error, as we are removing 3 leap days every 400 years (there are 3 out of 4 century years that are not being defined as leap years).
Timezones shifts can be greater than +12 hours or lower than -12 hours
Okay, we all know that working with timezones is a pain. But if a day has 24 hours (forget about Japan this time), and if we consider Greenwich meridian as UTC+0, then the maximum shift should be +12 hours or -12 hours, right? It doesn't have sense to have a UTC+14 timezone, right? Shouldn't that be UTC-10?
Well, let me introduce you to the Line Islands. The Line Islands are a group of atolls in the central Pacific Ocean, south of Hawaii, that are part of Kiribati. The Line Islands are the only place on Earth where the time zone is UTC+14. That means that when it is 14:00 in Line Islands, it is 12:00 in the nearby Baker Island (UTC-12). That is a 26 hours difference! So here is another bonus falsehood about time (take it as a 2 by 1 offer): different places in Earth can have more than 24 hours of difference between them too! (and we are not taking into account summer time changes!).
Also, the Antarctica, been in a pole, has a lot of timezones with shifts greater than 12 hours. For example, the timezone of McMurdo Station, when Daylight Saving Time is in effect, is UTC+13.
Do you want more about timezones? We might need to differentiate between Earth and Moon timezones soon.
Conclusion
Time is a complex thing. It is not as simple as we might think. There are a lot of exceptions and special cases that we need to take into account when working with dates and times in software development. We, as developers, need to be aware of these exceptions and take special care when working with dates and times in our code. Always ensure that you are using battle-tested libraries to manipulate dates and times.
As a last defensive resource, ensure that you are testing your code with different dates and times. Take into account different time exceptions and special cases, like those I showed you today, when you are building your test scenarios. Until next time!