CodeSOD: Time Changes

Dates and times are way more complicated than we usually think they are, especially when we're talking about historical dates and times. The solution, of course, is to always use someone else's work, whether it's a library or your language's built-ins, never implement date handling yourself.

For a long time, though, Java's date handling left something to be desired. Which is why Sven found this history lesson in his company's code base:

// Those annoying Germans have stolen 1 hour and 40 minutes from us on the 16th of may 1940
// and to this day they haven't returned them (like our bicycles).
boolean is16mei1940 = year == 1940 && month == 4 && day == 16;

// Before our neighbours came with the above 'suggestion' we did the same on the 1st of July
// 1937. We adjusted the time difference with Greenwich officially from 19 minutes 28 seconds
// to 20 minutes. We skipped the first 32 seconds after midnight.
boolean is1juli1937 = year == 1937 && month == 6 && day == 1;

// During the first World War the Netherlands decided that in the summer the clock
// would go back one hour, but in the first year this happened at midnight. Only a year
// later did people realise it was more convenient to do it at 2 o'clock in the morning.
boolean is1mei1916 = year == 1916 && month == 5 && day == 1;

calendar.setLenient(is16mei1940 || is1juli1937 || is1mei1916);
calendar.set(year, month, day);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);

I'll let Sven explain the bit about the bicycles:

The comment about Germans not returning our bicycles is an old joke in the Netherlands referring to the second World War during which the Germans confiscated large numbers of bicycles from Dutch citizens during their occupation of the Netherlands.

Given how much of this centers on Nazi occupation and also World War I, I wouldn't call this a fun history lesson, so let's get into the code.

The setLenient function controls how strict date parsing is. From the docs:

With lenient interpretation, a date such as "February 942, 1996" will be treated as being equivalent to the 941st day after February 1, 1996. With strict (non-lenient) interpretation, such dates will cause an exception to be thrown. The default is lenient.

You'll note, though, that we're not using parsing here. Which raises the question of: why is this happening? I can't say that I'm sure. Perhaps the documentation is misleading and the original developer found an edge case? Do they explicitly want to disable lenient parsing for some future parse operation Sven didn't submit?

But then we set various properties. The set method is overloaded, as you can see here, but what you don't see is that there's a 5 parameter version which lets you set the year, month, day, hour, and minute, all in a single operation. So I suspect that this could easily be a one-liner.

But, as always, the real WTF is how complicated date times actually are.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

This post originally appeared on The Daily WTF.

Leave a Reply

Your email address will not be published. Required fields are marked *