Friday, 18 January 2013

Passing DateTime information over (REST) API

I recently developed a RESTful API with the ability to schedule a task to be completed at a particular time in the future. The most challenging part of designing the API turned out to be deciding how to pass DateTime information around in a language agnostic manner.

I found very little information on the topic other than a few answers to questions people had asked, and no discussion about the merits or disadvantages of any particular method.

The Long:

There are a few ways that I have come across to solve this issue - serialization, unix timestamps and encoded strings being the most common.

Serialization is just a bad idea - this introduces language interoperability issues due to the incompatibility of data serialized from different languages. This also creates a security concern, injection attacks are possible if an attacker is able to man in the middle the connection. Please don't do this.

Unix timestamps work great if your application doesn't need to be time zone aware. If you think your application may ever need to operate across multiple time zones then timestamps aren't a good choice. The disadvantages here are the lack of time zone support, the inability to represent a DateTime before 1970 and the lack of human readability.

Encoded strings work if you stick to the same encoding format, however there are a number of pitfalls when interfacing with other applications. Make sure you document how this works somewhere for consumers of your API. Keep in mind that while '10/01/2013' may look obvious to you, in the US that would be 'MM/DD/YYYY' while in New Zealand it would be 'DD/MM/YYYY'.

The best way to encode a DateTime as a string is to follow a standard. From my research the most supported and well known seems to be the ISO 8601 standard which addresses all the concerns raised above, and also has the advantage of being mostly human readable.

The Short (with Python specific examples):

Encode your DateTime object as a string in time zone aware ISO 8601 format:

>>> from datetime import datetime
>>> from pytz import timezone
>>> datetime(year=2000,day=1,month=1,tzinfo=timezone('Pacific/Auckland')).isoformat()
'2000-01-01T00:00:00+11:30'

Decode your DateTime object using something like the iso8601 library.

No comments:

Post a Comment