I have written an alarm app for Android, called Fake Dawn. Friday I was talking to my friends, and we mentioned turning back the clock for daylight saving time (DST) on Saturday night, then proceeded to praise our phones that already do that automatically. Wait a minute: does my app work in this case? I was sure that I did not introduce code that specifically handles DST, so the alarm might fire one hour later or one hour earlier, and my users will curse me for waking up at the wrong time, maybe someone will lose their job, be late at their own wedding or forget to take a medicine!
So the first thing that I did was look at the code. My app lets the user choose which day of the week the alarm goes off, and in the code have a function to return the time of the next alarm by jumping to the next day with “
Calendar.add(Calendar.DAY_OF_YEAR, 1)” (See Java documentation). But if I set the alarm for 8:00AM on Saturday then add 1 day, which everybody knows is 24 hours, the alarm will fire at 7:00AM because on Saturday night the clock goes back 1 hour from 3:00AM to 2:00AM. I’m quite sure my app won’t work.
So I tested the behaviour of my app on my phone: it was Saturday at around 10:00AM, I set the alarm to 10:00AM excluding Saturdays, and then a message pops up indicating the time to next alarm: 1 day and 1 hour. Wait, shouldn’t it be 1 full day? I checked the code that prints the message and nothing seems wrong. So I printed the
Calendar object before and after adding a day, and it turns out both of them indicate a time of 10:00AM. So my app seems to work but I’m not sure why.
Another thought: what’s the difference between these two Java code snippets?
Calendar t = Calendar.getInstance(); t.add(Calendar.DAY_OF_YEAR, 1);
Calendar t = Calendar.getInstance(); t.add(Calendar.HOUR_OF_DAY, 24);
The first snippet takes the current date and time and adds 1 day. The second snippet takes the current date and time and adds 24 hours. Everybody knows that a day is composed of 24 hours, right? Then the two snippets have to behave in the same way, right? Turns out that the two snippets behave differently during DST transitions.
The physical time can be seen as linear, and the number of seconds from the beginning of the last epoch increments one second at a time. But we humans organized the physical time in more useful calendar fields such as minutes, hours, days, months and years. There are some natural causes (earth rotation and revolution) for which we need to adjust our fields to the nature: leap years, leap seconds are exceptions where a year might last more than 365 days and a minute might last more or less than 60 seconds. Then at some time in history we decided to change the value of these fields during particular days: the Daylight Saving Time approach. In this transition, a day can last 25 hours or 23 hours.
In this mess, Java code offers a way to don’t think about these exceptions that much. If you have a
Calendar object, you want to add a day, and call “
add(Calendar.DAY_OF_YEAR, 1)“, Java will add a day taking into consideration that the day might last more or less than 25 hours, and it will keep the smaller fields (such as hours and minutes) unchanged (as much as possible, see Add rule 2). The reason why my app works is that Java libraries take care of the complexity for me. And the reason why my message prints “1 day and 1 hour” instead of “1 day” is because in that message I assume that a day is made of 24 hours, but that particular day lasted 25 hours.
In conclusion I can sum up the following lessons:
- Test for daylight saving time transitions, leap seconds and so forth,
- Be aware of the assumption you are making in the code,
- Let the library manage the complexity that it’s coded to manage.
I hope to remember them.