We could argue this behaviour is misleading since we are configuring a transformation which, for calendars, only applies on the reading direction but for other types of dates applies bidirectionally.When it comes to handling and storing dates, the common standard for server applications is to handle and store all dates in UTC format, or at least in some kind of standard and deterministic format such as ISO 8601.
Recently though, we had a bit of a struggle getting one of our applications to work with dates. The problem On one side, this application relied on JVM defaults for timezones, in this case EuropeMadrid which can translate into GMT1 or GMT2 depending on the time of the year. On the other side, the same application exposes an API that receives dates in UTC format. This resulted in the application handling two kinds of dates: internal dates in GMT12 format and external dates in UTC format. These dates are internally represented as java.util.Calendar objects which are persisted to the database. Opengl 21 download for macThe mixing of timezones added to the particularities of the Calendar class being stored and retrieved by Hibernate made the CRUD operations involving dates inconsistent. We are going to demonstrate this scenario using a simple entity class which holds two calendars. Java Calendar Timezone Code Less VerboseNotice we use Project Lomboks fancy features to make our code less verbose. Instances of this class are written and read by means of this Spring Data JPA repository where weve added two commodity methods for the sake of this demo (and also to override Hibernates cache): To simulate what our application does, lets take a look at this code: In brief, we create two calendars belonging to the UTC and GMT1 time zones respectively and we simultaneously write them to the database. Using the logCalendar utility method above, we print each calendars epoch, hour of day and time zone: Written GMT1 Cal - epoch: 1551949200000 - hour of day: 10 - timezone: EuropeMadrid Written UTC Cal - epoch: 1551952800000 - hour of day: 10 - timezone: UTC Notice the actual epochs are different since 10AM GMT1 and 10AM UTC are not the same hour. But, what happens when we read the dates back from the database We have this output: Read GMT1 Cal - epoch: 1551949200000 - hour of day: 10 - timezone: EuropeMadrid Read UTC Cal - epoch: 1551949200000 - hour of day: 10 - timezone: EuropeMadrid What have just happened here Everything seems to have worked fine for the GMT1 calendar since it shares the same timezone as the JVM. However the UTC calendars been directly stored in the database and then loaded into a GMT1 one with no hour transformation being performed. Keep in mind that 10AM UTC should result in 11AM GMT1, so this behaviour is not what we should expect. Configuring Hibernates JDBC timezone As introduced by this post in the official Hibernate blog, since Hibernate 5.2.3 we can make use of the hibernate.jdbc.timezone property to make the way dates are stored independent from the JVMs default timezone. This seems a good fit for us, we can make all dates be stored back and forth in UTC format. Notice, as well, the epoch has been preserved between write and read. Unluckily, the GMT Calendar has been also added an hour, notice the epoch has changed. Apparently this setting is not performing date conversion on both directions as promised by the author of the post, it seems to only be working on read operations. GMT1, this is the output for such scenario: Written GMT1 Cal epoch: 1551949200000 hour of day: 10 timezone: EuropeMadrid Written UTC Cal epoch: 1551952800000 hour of day: 10 timezone: UTC Read GMT1 Cal epoch: 1551949200000 hour of day: 10 timezone: EuropeMadrid Read UTC Cal epoch: 1551949200000 hour of day: 10 timezone: EuropeMadrid Well, the result is we are back at the starting point before any configuration was done. Doing it, we get to the code of the binder: And to the code of the result extractor: As we can see, write operations ignore the timezone configured by the property when dealing with calendars, as in our example. In this cases, the timezone of the calendar prevails over the configured one. Conversely, on read operations theres no distinction between calendars and other type of objects, so the dates stored in the database will always be interpreted according to the configured timezone.
0 Comments
Leave a Reply. |
AuthorKelsey ArchivesCategories |