I’ve been a professional developer for about six years now. During those six years I’ve never worked for a company or on a project that didn’t struggle with date and time issues in some form.
Nearly every application you will work on requires the use of time in some way, meaning that at some point you’re going to have to collect, store, retrieve and display dates or times. There’s no silver bullet for dealing with dates or times and you can never escape the inherent complexity that comes with our concept of time, but there are steps you can take to make it less of a pain.
In the years that I’ve been working with time across different programming languages, I’ve found the following knowledge goes a long way.
Choosing the Right Data Format
The first step when working with times and dates is to choose a representation for your data. While different formats may seem more or less the same, the format you choose will have a large impact on how you write and debug your code.
Using a numeric timestamp when you need a date will mean parsing the date timestamp and retrieving the date from that, which may or may not be straightforward depending on the time zone.
Using a custom string to represent a span of time seems easy to store and manipulate, but it’s difficult to query. Additionally, using any kind of representation that isn’t immediately recognizable by the human eye is going to make debugging your code more difficult.
When choosing a format for dates or times, I abide by the following rules:
- Never use numeric timestamps. They’re often the easiest to obtain by standard libraries among various programming languages but they’re not human readable and the temptation to manipulate them is too strong.
- Abide by ISO 8601, a standard that defines a format for date and time-related data. It’s trivial to find a library for any language that can handle the variations of ISO 8601.
- ISO 8601 is a standard, but it has many variations. You should always choose the most human-readable variant of ISO 8601. This requires no extra effort but makes debugging easier.
- Your timestamp string should only contain data you absolutely need. When working with times your string should not contain a date and when working with a date that is time zone-agnostic your string should not contain a time zone. Adding extra information adds ambiguity to the parsing operation and to the intent of the data for future developers
- When storing time zones always normalize to the same time zone in your timestamps. This not only makes it easier for a computer to sort and process the data but it makes it easier for a human developer as well.
Abiding by these rules won’t cost you much up front but they will make your life easier when your application is established and you find that your usage of times and dates isn’t what you expected.
Choosing the Right Tool
As with most problems in our industry, time and date handling comes down to picking the right tool for the job.
A good library for handling dates and times will allow you to follow the 5 rules mentioned above. Specifically, it should be able to:
- Parse any date representation you may run into (including external representations.)
- Output to any date representation you may need (including external representations.)
- Manipulate dates and times by adding or subtracting units of time from them.
- Compare dates and times.
- Correctly convert between time zones.
It’s important that your library supports these features, otherwise the temptation to try to implement the functionality yourself will be too high. And just to be clear, if you try to implement any of that functionality yourself, you will fail.
Don’t parse your own timestamps with regular expressions, don’t add seconds to a numeric timestamp because it seems like a normal number and don’t compare dates and times using the equality operator. These libraries exist because these problems are hard to solve and reinventing the wheel in your application is just going to leave you with a broken wheel.
Below I have a few suggestions for libraries that fit these criteria:
|Java 8 and above||Standard Library (java.time)|
|Java 7 and below||Joda-Time|
If your language isn’t listed (because I’m not familiar enough with it) just search for <language> date and time library. Chances are you’ll find a good library that will do everything you need.
Knowing About Time
The final bit of knowledge I have to share isn’t specific to working with dates and times, but is more of a general philosophy to help us avoid problems and it applies to date and time handling as much as it does every other problem in programming.
Always check your assumptions.
We approach every problem presented with a large body of knowledge and an even larger body of assumptions. When handling dates and times it’s more important than ever to check your assumptions to ensure that they still hold for your scenario.
This list, titled Falsehoods Programmers Believe About Time, gives many excellent examples that illustrate time probably isn’t what you thought. When you’re designing or developing a feature that centers around time I encourage you to grab a partner and go through this list ensuring that you’ve avoided the pitfalls listed.
Time bugs are notoriously difficult to catch and even more difficult to test for. If you develop with this list in mind you may be able to avoid subtle bugs that would affect your customers but that they might not catch (the worst kind of bug!)
No discussion about times or dates would be complete without mention of time zones. In addition to familiarizing yourself with the common falsehoods listed above, also familiarize yourself with the basics of time zones.
Time zones will consistently be a pain point when working with time, even if you think you have them “all figured out”. Having a bit of knowledge about time zones will help you center your thinking and help ensure that you don’t make any logic errors when manipulating times.
Unfortunately there is no way to completely avoid the difficulty of storing and manipulating times and dates when programming. But if you follow these steps and work with this knowledge in mind, you can make the task easier by cutting down on the amount of code you have to write and forcing yourself into paradigms that are less likely to cause issues.