ZonedDateTime持久到SQL数据库

时间:2017-01-24 20:38:19

标签: java mysql time timezone zoneddatetime

美好的一天,
我创建了Web应用程序服务,该服务将在全世界范围内使用。
因此,我需要以UTC格式存储日期时间值,并在最终用户的墙上时间中以时钟表示它们 读完Stack溢出后,我明白了,我应该:

  1. 将时间戳用作DB中的列类型(当前为MariaDB 10.1.20)
  2. 在Java中使用ZonedDateTime(我使用java8)
  3. 在这些值之间进行转换时出现了问题 当我使用JDBC时,我必须进行以下转换:

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

    我的代码:

    // 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))
    

    当我使用时:

    zonedDateTimeBeforeSave.isEqual(zonedDateTimeAfterSave);
    

    它返回false(我需要在我的域模型的重写等方法中比较它们)
    以下是打印出来的两个:

      

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

    问题:

    1. 我的选择是对的。也许,我应该使用另一个列或java类型......
    2. 我是否正确进行转换。也许还有另一种更好的方式
    3. 谢谢

      1. 编辑: 在马特约翰逊的帮助之后,我明白问题在于,当我将日期时间保存到DB时,它不会保存分数,尽管它应该。 FYI列类型是时间戳(6)。
      2. 编辑: 现在我使用java.time.Instant而不是ZonedDateTime

2 个答案:

答案 0 :(得分:1)

我在阅读完这篇文章和评论后终于发现了问题:

  

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

原因是我的MariaDB JDBC驱动程序
我有一个旧的1.1.7版本和参数&#34; useFractionalSeconds&#34;设为假 解决方案是将此参数设置为true(f.ex by URL) 或更新驱动程序。目前的最新版本是2017年5月25日的1.5.7

答案 1 :(得分:0)

MySQL增加了对版本5.6.4的小数秒的支持。我的猜测是你正在运行比这更早的东西,因此你的毫秒被截断了。

来自MySQL 5.6文档:

  

在MySQL 5.6.4之前,实例是有限的,其中在时间值中允许小数秒部分。在诸如文字值之类的上下文中以及在某些时间函数的参数或返回值中允许尾随小数部分。 ...但是,当MySQL将值存储到任何时态数据类型的列中时,会丢弃任何小数部分而不会存储

     

MySQL 5.6.4及更高版本扩展了对provaButton = new AjaxLink("prova_btn"){ @Override public void onClick(AjaxRequestTarget art) { getChannelManagerAPI().getToken(new ChannelManagerCallbackWrapper() { @Override protected void onSuccess(Object object) { Object[] response = null; response = (Object[]) object; for (Object obj : response) { info("Result " + obj.toString()); } } @Override protected void onFailure(Throwable throwable) { info("Errore nella chiamata : "+ throwable.getMessage()); } }); refreshFeedBackPanel(art); } }; add(provaButton); TIMEDATETIME值的小数秒支持,精度高达微秒(6位)。 ...

如果您愿意,请将此文档中的更改与版本5.55.65.7进行比较。