【问题标题】:How to convert from java.sql.Date to ZonedDateTime如何从 java.sql.Date 转换为 ZonedDateTime
【发布时间】:2017-02-08 06:47:36
【问题描述】:

我正在尝试从 java.sql.Date 转换为 ZonedDateTime。这是我正在使用的代码

ZonedDateTime.from(new java.util.Date(result.get(0).getTime()).toInstant())

但是会导致如下错误-

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: 2016-09-29T18:30:00Z of type java.time.Instant

有没有办法进行这种转换?

【问题讨论】:

    标签: mysql spring zoneddatetime


    【解决方案1】:

    tl;博士

    ZonedDateTime zdt =
        myJavaSqlDate.toLocalDate()
                     .atStartOfDay( ZoneId.of( "America/Montreal" ) ) ;
    

    详情

    不要将旧的日期时间类与 java.time 混合。避免旧课程。所以你打电话给java.util.Date 没有帮助。

    知道java.sql.Date 表示仅日期值,没有时间和时区。不幸的是,它实际上确实有时间和时区,但我们应该忽略这些事实。这是一个设计不良的类黑客。仅当您还没有支持 JDBC 4.2 和 java.time 类型的 JDBC 驱动程序时才使用它。

    因此,当您必须使用 java.sql.Date 时,将其值转换为 LocalDateLocalDate 类表示没有时间和时区的仅日期值。

    要与 java.time 相互转换,请查看添加到旧类的新方法。

    LocalDate ld = myJavaSqlDate.toLocalDate();
    

    往另一个方向发展。

    java.sql.Date myJavaSqlDate = java.sql.Date.valueOf( ld );
    

    如果您的目标是从仅日期值中获取日期时间值,则需要指定时间。如果您想要一天中的第一刻,让 java.time 为您确定一天中的那个时间。由于夏令时 (DST) 等异常情况,时间00:00:00并不总是一天的开始。处理此类异常需要您指定时区,因为每个时区都有自己的异常规则。所以应用ZoneId 来获取ZonedDateTime 对象。

    ZoneId z = ZoneId.of( "America/Montreal" );
    ZonedDateTime zdt = ld.atStartOfDay( z );
    

    关于java.time

    java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

    Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

    您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

    从哪里获得 java.time 类?

    • Java SE 8Java SE 9 及更高版本
      • 内置。
      • 标准 Java API 的一部分,带有捆绑实现。
      • Java 9 添加了一些小功能和修复。
    • Java SE 6Java SE 7
      • 大部分 java.time 功能都在ThreeTen-Backport 中向后移植到 Java 6 和 7。
    • Android
      • 更高版本的 Android 捆绑包实现 java.time 类。
      • 对于早期的 Android (ThreeTenABP 项目采用 ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…

    ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

    【讨论】:

    • 虽然这些不应该混合是非常正确的,但请注意海报使用的是弹簧。我来到这里是因为我可能遇到了与他们相同的问题:当查询方法的结果是 datetime 而不是实体时,spring-data 在某些情况下会将其 only 转换为 java.sql.Date ,即使 hibernate 允许使用 ZonedDateTime 字段持久化实体。在这种情况下,我们不是因为我们想要混合它们,而是因为我们绝对没有其他选择,只能进行返回实体的查询,或者完全放弃 spring-data。
    【解决方案2】:

    您所能做的就是将时间设置为一天的开始时间更改为本地日期时间,因为 java sql date 没有时间组件。使用时区或默认系统时区来获取分区日期时间

    ZonedDateTime zonedDateTime = ZonedDateTime.of(result.get(0).toLocalDate().atStartOfDay(), ZoneId.systemDefault());
    

    【讨论】:

      猜你喜欢
      • 2021-05-27
      • 1970-01-01
      • 1970-01-01
      • 2014-04-19
      • 2021-04-29
      • 1970-01-01
      • 2011-08-29
      • 2017-07-13
      • 2013-01-27
      相关资源
      最近更新 更多