Dates and times, like character encoding, are tricky to get right. In real life the concept of time is not something we usually think about much (except when we skipped breakfast this morning and it’s still only 10:30) but once you start storing and manipulating dates and times with computers you begin to run into all sorts of complications like time zones and durations and leap seconds and when is it really the ‘start of the day’ anyway?
Probably the biggest problems with dates come from time zones. Time zones are more complicated than they first appear. They are not just an offset in hours (or half hours) from UTC but also a set of rules about when and if daylight saving time comes into effect.
A good date and time library like Joda-Time or the new java.time API can make things easier but regardless of the tools being used I have found a few simple rules can make working with dates and times a bit more sane and save you having to take your site down for maintenance when summer time rolls around.
Keep your server’s clock in UTC
I have never found it useful to run a server in a time zone other than UTC. When you build a new server make sure one of the first things you do is set the system clock to UTC (remember to reboot or restart your system log so it picks up on the change). This will make inspecting logs so much easier as you won’t need to wonder whether the timestamp in the log entry is in UTC or whatever time zone your server is in or whether it was summer time when the log was written. It will also help reason about when cron jobs will actually run.
Keep your database in UTC
Just like the server itself, make sure your database is running in UTC. Many databases will use the system time zone by default so if the server it’s on is in UTC there’s a good chance the database is too but it can be helpful to explicitly set it.
Keep your JVM in UTC
Java has a default time zone it uses for date operations that don’t specify one. So does Joda-Time. You can set the user.timezone system property or set it directly using TimeZone.setDefault(timeZone). I tend to set it during application startup with something like this (also sets Joda-Time default):
TimeZone timeZone = TimeZone.getTimeZone("UTC"); TimeZone.setDefault(timeZone); DateTimeZone.setDefault(DateTimeZone.forTimeZone(timeZone));
Store and work with dates in UTC
Joda-Time may help you work with time zones but for many applications you don’t really care about a time zone until it comes time to either accept data from or present data to the user. Until that time comes keep your dates in UTC. Keep them in UTC for as long as you can and whatever you do, unless you must record the time zone of a date, store it as UTC in your database.
You may have spotted a theme; keeping your dates in UTC for as long as possible can really help you to reason about what your code will do and when it will do it. If you only work with dates internally and don’t need to present a localised date to a user then you can just keep everything in UTC all the time and never worry about summer time again.
Start date is inclusive, end date is exclusive
Once you stick to this rule, date ranges become so much easier to work with. For example, if I were to specify ‘this week’, the start date would be 2015-01-04T00:00:00Z and the end date would be 2015-01-11T00:00:00Z. You will have no trouble comparing instants to a date range if you follow this rule.
For some reason this seems to be a tricky concept for non-programmers to grasp so you will no doubt have to put up with requirements being specified using times like 23:59:59.
Use ISO 8601
Finally, where possible stick to the ISO 8601 formats for representing dates and times. Like all the above rules this one helps eliminate ambiguities and inconsistencies.