4 steps to returning a correct timestamp in an API

Gerard Lutterop
yourapi
Published in
6 min readMay 1, 2018

What could be more boring than returning a timestamp from an item in an API. Just return the time and you’re done, right? Most developers try to evade this boring subject and after reading the introductory lines to this subject in their tool of choice (a programming language, a database or some representation language like json) they shake their heads and just go with the ‘naive’ time, since the subject is simply too complicated to grasp.

Different places, different times…

The concept of time zones is easy to understand, but there are many choices to make when providing an API. We live in Europe and our country only has one time zone, so it is natural for us to think only in ‘the’ time, which is the current time we see on our clocks, aka the naive time. But for people in countries with multiple time zones it comes more natural to think in multiple time zones, but also have more options to get it wrong. So what’s the right approach in returning a timestamp? We’ll find out in 4 steps.

Naive timestamps are the way to go when you start deploying your first system. You have too much to think about anyway, so you just skip this subject and install all the servers and services with the default settings (just choose your country and locale settings). Everything is just fine, until it isn’t.

The first hickup is, when you do some analyses and find out that in your daylight saving time there’s a hole in the logging when daylight saving time (DST) starts and at the end of DST the log entries are duplicate, you can’t decide on the exact time, because the clock made a mini time travel. No great harm done, but inconvenient.

The next inconvenience comes when you build an interface on it for others to use and you provide the time ‘as is’. People using your system may have a different notion of what ‘as is’ means, so the time quickly gets ambiguous.
You realize that when your great system grows and people in other time zones use your system, you have to find a way to translate your system time to their time. Since your time changes twice a year, this gets quite complicated. Now you realize why this is called ‘naive timestamps’ and you decide to do it better next time.

Unix Epoch time solves this problem very nicely. It is universal, unequivocal and very easy to do calculations with. You suddenly understand why it is so widely used and decide to use it in your next project. You’re going to do it right this time!

You carefully craft your interfaces, variables etc to all use epoch time. When you’re done, you proudly present this solution to your users, who come back to you the next day saying: ‘Can you tell me when 1524751342 was? That’s when an order was made.’
And when you look at log files and try to find the logs of last night, you realized that you might have made it only worse. You can’t even simply go back one hour yourself! Now you realize why it is so easy to do calculations with and why computers just love Epoch timestamps. Epoch timestamps should never be used in an interface, despite all the arguments by hardcore programmers. You’ve learned your lesson and decide to do it better next time.

Timestamps with time zones are a difficult subject, but you decide to plunge in and make it work right this time. So you read about storing timestamps with time zones in your database of choice, find out about how to represent them in your programming language and presenting them in your interface.

So you craft the new interface, decide to apply the ISO8601 standard and make sure no information is lost ‘down the way’ or ‘the way up’, test it carefully and present your interface. The timestamps are now human readable (solving the epoch problem) and unequivocal (solving the naive problem). But although these problems are solved, your users still aren’t completely satisfied. When a user in NY enters an order, it is displayed as 2018–04–27T13:23:30–04:00, while at that same time in San Francisco an order is entered as 2018–04–27T10:23:30–07:00. Depending on who entered it, the timestamp is different because of the local timestamp. This timestamp is actually displayed as-is to every user, so an east coaster has to mentally translate a west coast time and vice versa. Your American users also don’t like the ISO format, they prefer the AM/PM like they are used to. This also takes extra effort and room for errors by your front end programmers.
So you realize you are nearly there, have an unequivocal and (nearly) human readable format. On to the definitive solution.

UTC is the name of the definitive solution. Formerly known as GMT, this is the Coordinated Universal Time (by some weird compromise abbreviated as UTC). UTC is the standard time with time zone 0. By converting all entered timestamps to UTC before storing them, they are stored in one timezone: UTC.

When an east coaster enters an order, it now has the same time stamp as when a west coaster enters it. The only problem remaining then, is conversion to a user friendly format.
From the point of view of the API provider, the most easy solution is to leave it at that. But this is transferring the complexity of presentation and timestamps to the user of the API. Of course there are lots of fine JavaScript libraries to solve that problem.
But for many uses (like display of raw data) it is preferable to switch time zone and the presentation format. Also for entering a timestamp it should be as forgiving as possible.

Therefore you decide to make your API as flexible as possible. For retrieving data, you can specify a timezone and a time format. So retrieving an item from the api with https://url?tz=PDT&tf=US gives the time as a local west coast time, formatted in plain American format: {"timestamp": "4/27/18 3:18PM"} while https://url gives the time as UTC: {"timestamp": "2018-04-27T22:18+00:00"}. You can also support Epoch for returning the timestamp: https://url?tf=epoch gives the time as : {"timestamp": 1524867480}.

The reverse should also hold: when entering a timestamp, your user should have the option of specifying the time zone and format. When entering an integer or floating point number, the input system should automatically interpret it as an epoch.

At yourapi, we have have learned these lessons over a remarkably long period of time. We are at step 3 at the moment and are preparing for the final step, which gives the users of yourapi ultimate flexibility in an unequivocal format.

--

--