Montag, 4. November 2013

Joda Time to JDBC in three hard lessons

Converting from the popular Joda Time library types to JDBC is a common task that is repeated in many libraries and projects. Many times it is done wrong, resulting in all kinds of time related bugs. I walked into this trap myself and would like to settle this once and for all.

First Lesson: Fear the DST!

The simplest implementation which you will find in many libraries just uses the default time zone everywhere. This error is even present in Joda Time's own Hibernate integration project.

This breaks on the transition to DST. By advancing the clock one our, we end up with times that do not exist. For instance new LocalDateTime(2014, 3, 30, 2,0).toDateTime() will crash in CEST, because the clock advances from 01:59 directly to 03:00.

Second Lesson: Calendar.getInstance() is slow!

So to work around this, we need to specify a time zone that has no DST. Our best candidate is of course UTC. But when we use UTC for conversion to the Timestamp, we also need to tell the JDBC driver to use UTC. This can be done by an additional Calendar argument.

At first I used a new Calendar instance each time this method was called, which resulted in pretty bad performance.

Third Lesson: Don't trust vague JavaDoc!

So I refactored towards a constant Calendar. I knew that Calendars are not thread safe. But the JavaDoc says that it is only used for specifying the timezone and locale to use. So this implies that the Calendar will not be written to and can thus be shared among threads.

Well, it turns out that the Oracle SQL driver does use this Calendar for calculations, so you end up with several threads writing the one instance, resulting in garbage data.

Finally - working and fast

So finally I replaced the shared Calendar with clones. That's much faster than obtaining a new instance, but safe at the same time. I can only recommend you do the same for your converters.

Special thanks go to Sun for getting us into this mess in the first place through Java's horrible Date/TimeStamp/Calendar API.