The DateTime Environment Trap
Recently we had a deployment of an application to one of our production servers, everything was thoroughly tested in all environments; Dev, Integration, QA and UAT, and successful, so a deployment to Production was scheduled. The application was thusly deployed and suddenly BANG! it didn’t work, but how? We were sure it was working in all our environments leading up to this deployment! So we quickly rolled back and started to investigate the log messages and error messages in our logging system. From this we then discovered that there was a date time string parse exception or FormatException. The issue was that one of applications, let’s call it Application A, would write a message to a message queue containing a string with a date inside it, then, another application, which we will call Application B would then see this message on the queue and take it down for processing, this Application B would then parse this string into a datetime object.
So the question is why would this work in all environments and then not in production?
Well, as the world migrates to a full cloud based infrastructure, so are we, however our test environments for Application B are hosted in-house in the UK and our production environment is in the cloud on AWS, but on a US server, we didn’t think this would be a problem. Application A which writes to the message queue is hosted on a UK server in production. So when Application A writes to the message queue and creates this datetime object, it creates it in a UK datetime format and when Application B then reads this message from the queue and tries to parse it as a datetime object. But, it uses the US regional settings to attempt to parse it as a US datetime object, or M/d/yyyyas opposed to dd/mm/yyyy and as a result we get our FormatException, but only in some cases, more on that in a bit.
So what is the solution?
The solution is to use the international standard DateTime format known as ISO 8601. Excerpt from the Wikipedia article:
The purpose of this standard is to provide an unambiguous and well-defined method of representing dates and times, so as to avoid misinterpretation of numeric representations of dates and times, particularly when data are transferred between countries with different conventions for writing numeric dates and times.
That way when Application A writes to the message queue and adds a datetime object as a string using the ISO 8601 format it will use yyyy-mm-dd and Application B will consume that same message and parse this string correctly as a result, no matter whether the Application A is hosted in the UK or the US.
Be aware, you should handle dates with care. There are some gotcha’s that could happen in this scenario and it will still work in production if you don’t have the ISO 8601 format enabled for handling dates. Let’s say for example you have a Product Inventory system, whereby a date is added for when a product will be scheduled to be taken out for delivery from the warehouse. The application that writes an order to be processed could be hosted in a UK environment and request that the item be dispatched on 1/12/2014, in the UK that would mean dispatch on the 1st of December 2014. However, let’s say the order inventory system that processes that product order message is hosted in the US, it will retrieve that date and parse it as the 12th of January 2014. At the time of writing: 2014-10-30 (sorry, keeping with the theme of this post) the order will never be dispatched, this is because the date to dispatch is in the past, but it will flow through the system correctly, as the US application will handle and parse the date with no issues, unless you have some error handling logic that prevents product orders in the past, but it still won’t hide the fact that there is an issue with the date handling. However, when the order is sent for processing for say the 13/12/2014 by the product ordering system then the product inventory system will throw theFormatException as there isn’t a 13th month in our calendar.
So this was a recent pain we had to go through, but pain isn’t so bad, pain helps with learning, learning is good and helps us create more awesome! If you have any similar programming war stories the world should hear and would like to share, add a comment below.
Thanks for reading and keep building awesome.
Until next time!
P.S. You can also find me on Twitter: @ianaldo21