简体   繁体   中英

ZonedDateTime persistance to SQL Database

Good day,
I create web application service, which would be used across the world.
Therefore I need to store datetime values in UTC and represent them in clocks on the wall time to the end user.
After reading Stack overflow, I understood, that I should:

  1. use timestamp as a column type in DB (currently MariaDB 10.1.20)
  2. use ZonedDateTime in Java (I use java8)

The problem arose while converting between these values.
As I use JDBC, I have to do the following conversion:

java.sql.Timestamp <-> java.time.ZonedDateTime 

My code:

// Get current zonedDateTime
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneOffset.UTC);

// Convert zonedDateTime to java.sql.Timestamp before saving to DB
Timestamp = Timestamp.from(zonedDateTime.toInstant());

// Get zonedDateTime from resultSet
Timestamp timestamp = (Timestamp) resultSet.getObject("created");
ZonedDateTime zonedDateTime = 
    ZonedDateTime.ofInstant(ts.toInstant(), ZoneOffset.UTC))

When I use:

zonedDateTimeBeforeSave.isEqual(zonedDateTimeAfterSave);

It returns me false (I need to compare them in overridden equal method of my domain model)
Below is print out of both:

zonedDateTimeBeforeSave: 2017-01-24T20:18:17.720Z
zonedDateTimeAfterSave: 2017-01-24T20:18:17Z

Questions:

  1. Am I right in my choice. Perhaps, I should use another column or java type...
  2. Am I right in doing conversions. Maybe there is another better way

Thank you

  1. Edit: After Matt Johnson's help I understood that the problem is in the fact, that when I save datetime to DB, It doesn't save fractions, though It should. FYI column type is timestamp(6).
  2. Edit: Now I use java.time.Instant instead of ZonedDateTime

I finally found out what was the problem after reading this post and comments:

http://mysqlnoob.blogspot.com/2016/09/replication-from-mysql-56-to-mariadb-10-fails-with-fractional-seconds.html

The reason was my MariaDB JDBC driver
I had an old 1.1.7 version and parameter "useFractionalSeconds" was set to false.
The solution is rather setting this parameter to true (f.ex by URL) or update driver. Current latest version is 1.5.7 as for 25.01.2017

MySQL added support for fractional seconds with version 5.6.4. My guess is you are running something older than that, and therefore your milliseconds are being truncated.

From the MySQL 5.6 docs:

Before MySQL 5.6.4, the instances are limited in which a fractional seconds part is permitted in temporal values. A trailing fractional part is permissible in contexts such as literal values, and in the arguments to or return values from some temporal functions. ... However, when MySQL stores a value into a column of any temporal data type, it discards any fractional part and does not store it .

MySQL 5.6.4 and up expands fractional seconds support for TIME , DATETIME , and TIMESTAMP values, with up to microseconds (6 digits) precision. ...

If you like, compare the changes in this doc from versions 5.5 , 5.6 , and 5.7 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM