In previous episodes, we talked about how dates and times have been used historically and how computers deal with them. In this episode, we’re going to discuss best practices that you can use while writing code that needs to work effectively with dates and times.
Best practices can help protect you from preventable errors and make it easier to reason about the code. We’ll discuss 17 bad assumptions that developers make and how to mitigate them.
“The mitigation strategies come from several other places, mostly from Will’s experiences and some of mine.”
Date and time libraries exist for a reason. That reason is because dates and times are complex to deal with programmatically, especially if they aren’t the main purpose of your application. Most developers will use such libraries to cut some of the complexity out of their day. However, even with good libraries, there are a number of things that can still prove troublesome when dealing with dates or times. You’ll have to protect yourself against them, because they are likely out of scope for whatever library you are using. Being smart about this can reduce the risk of screwy bugs when time-related issues occur.
13:00 Assuming a day is 24 hours.
This is true, except when daylight savings time changes. This is best mitigated by most developers by making it someone else’s problem, ie., using a library.
13:55 The number of hours in a day is a whole number.
This happens unless the UTC offset gets changed, which can be done by a government. Also, leap seconds exist including the theoretical possibility of negative leap seconds. If your system needs to know something by the second, measure seconds and convert to hours later. If it doesn’t, then round as needed. This is more of a discussion of how much precision is required.
16:43 The first week of the year starts on January 1st.
International Standards Organization (ISO) weeks have a definition and assume the week starts on Monday. January 1st is not always a Monday. This can throw week numbering schemes off. It’s important to remember that the first ISO week of a year can start in the previous year, whereas the common understanding is possibly not the same.
20:30 Given a local DateTime and location, I can derive UTC time.
When daylight savings time is occurring (fall back), the same local time can map to two different UTC times. In other words, you don’t know if they are talking about the time before or after the time fell back. In the other direction, some local times can be specified, but don’t actually exist, when the date is springing forward.
“It’s only at certain times that you can not make this assumption.”
Thankfully, these are mostly when people are asleep, so you’ll have fewer opportunities for issues. If a time is going to occur in the window of a shift to DST, you need to prompt the user to find out which one they mean. If a time is going to occur in the window of a shift from DST, you need to prompt the user to point out this issue and collect a different time.
25:30 Daylight savings time doesn’t always move the clock back or forward by an hour.
“Because bureaucrats are jerks.”
Some clocks only move it by 30 minutes. You can’t make assumptions about DST. Use a trusted, up to date library.
28:45 DST is observed in the first half of the year and not observed in the last half.
Well except for the half of the planet below the equator. Don’t write your apps with the assumption that your local conditions are the conditions for the rest of the globe. Convert from UTC to the user’s local time, rather than trying to do the DST calculations yourself.
32:20 DST starts in spring and continues until the fall.
“Daylight savings time is not scientific, it’s political football.”
Morocco suspends DST during Ramadan because of people fasting and all the events at night. You can’t rely on Daylight Savings Time to always be the same. Build your apps to either offload the work of determining DST or to ignore it.
33:30 I can store future timestamps as UTC and then convert it accurately.
Well, unless they change timezone rules. If it’s critical to get it right and the input came from a user’s local time, you may want to store both, so that in the worst case, you have some chance of correctly updating.
34:25 Time zone rules are static.
Don’t assume that variables are constants, especially when every government on the planet can get in on the action. Watch for when timezone updates come out and message the users in the impacted zones if you need to do so.
35:15 I can trust my OS to keep the time accurately.
If your computer is running in a Virtual Machine (VM), there is also the possibility of the clock being incorrect because the VM was paused and resumed. Network issues can also cause the system clock to be wildly inaccurate. Get your time from an authoritative source if it is that critical. Don’t trust time sources whose accuracy is less than the level of accuracy you require.
39:10 Shorthands for timezone identifiers are unique.
“The was really bad as software became international.”
CST can mean Central Standard time (US), Central Standard Time (Australia), Cuba Summer time, etc. You need to collect and store the real time zone specifier, not a shorthand for same. This doesn’t mean you have to display it that way for the user, but you need to have the right value stored.
39:58 You can calculate the number of seconds between any two UTC timestamps more than 6 months in advance.
Unless leap seconds are announced in the intervening time. If it isn’t critical, then ignore the possibility. You may need to store the appropriate values and adjust. You may also want to store a start time and duration, rather than storing both ends.
41:55 You can store any date you want.
“You can so long as that date is after 1970.”
Historical dates will likely give you problems, as DateTime types tend to be optimized to handle more recent dates. Not only that, but very old dates may be encoded in a different manner, and you’ll need to be able to convert it to something compatible in order to involve it in calculations with newer dates. You may need to use a different or specialized data type to store and process historical dates.
44:00 Adding an offset to a date will give a result that will make sense to humans.
Well, maybe, it might. However, given leap seconds (in either possible direction), DST changes, known changes to timezone rules, etc., you might be surprised. Determine whether adding the offset is intended to handle time as understood by UTC or by humans and use the appropriate version.
45:07 When making a thread sleep, you can trust the number of milliseconds you provide to be respected.
For instance, if you call Thread.Sleep(1000), you’d expect it to sleep for one second. Or for more than one second. However, system timers have granularity. They may not be accurate to the number of milliseconds you are expecting.
“You have a latency built in just for the machine understanding that clock pulse.”
You might also be in a VM that is paused. Or the system might be under load and not get back to you for a minute, depending on how thread scheduling is implemented. Assume that a thread sleep is of relatively fuzzy accuracy, or just avoid it altogether.
49:45 Assuming that clock ticks advance monotonically.
For instance, the windows timer tick count was a 32 bit integer, which meant that it rolled over every so often. Don’t do this. Tick counts aren’t intended to be used for this.
51:40 Your software will never run on a spaceship orbiting a black hole.
“I’ve worked in codebases that were the programmatic equivalent of a black hole…”
Once relativity gets into the mix, things are not going to work well, especially if your measurement of time has to match that outside. Realistically, we don’t have much in the way of protocols to correct this.
Hack a Typewriter to Tweet What You Type
With this project you take an old typewriter whole and using a micro controller convert it to a twit-writer, tweet-writer? The project starts by recognizing that all the keys you’ll need to tweet might not be on an older typewriter so you’ll need to add them. They use a Particle Photon microcontroller because it comes with wifi enabled but you could technically use any that you have available and add a wifi dongle or hat. They also get creative with reading the key strokes as the Photon only has 18 mixed-signal GPIO and a typical typewriter has around 50 keys. To mitigate this they toggle between rows of keys.
Tricks of the Trade
Know what charity costs before engaging in it.