【问题标题】:Saving date in UTC in Oracle Timestamp column在 Oracle 时间戳列中以 UTC 保存日期
【发布时间】:2020-01-14 19:50:54
【问题描述】:

我需要在 TIMESTAMP WITH TIMEZONE 类型的 Oracle 列中保存当前 UTC 日期和时间。这是来自带有 JPA 和 Hibernate 的 Spring Boot 服务

我在我的应用程序 yml 中启用了以下功能

  jpa:
    hibernate:
      ddl-auto: none
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.Oracle12cDialect
        jdbc:
          time_zone: UTC

Entity 类字段看起来像

@Column(name = "last_user_edit_date", columnDefinition = "TIMESTAMP WITH TIME ZONE")
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
private ZonedDateTime lastUserEditDate;

在设置日期时我正在使用

obj.setLastUserEditDate(ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("UTC")));

以上对于实际日期值来说工作正常。唯一的问题是在数据库中它正在保存 UTC 时间,但提到 MST(我的本地时区)作为时区。例如,保存的值是

12-SEP-19 09.50.53.820000000 PM 美国/丹佛

这里的 9.50 PM 实际上是 UTC 时间,但时区是 AMERICA/DENVER。我想要的是

12-SEP-19 09.50.53.820000000 PM UTC

我怎样才能实现这个 Spring JPA 和 Java 8 类?

谢谢

【问题讨论】:

    标签: spring oracle spring-boot java-8 spring-data-jpa


    【解决方案1】:

    LocalDateTime 是错误的类

    LocalDateTime 类无法及时跟踪。我无法想象调用LocalDateTime.now() 有意义的场景。在使用类之前阅读 Javadoc。

    跟踪片刻:InstantOffsetDateTimeZonedDateTime

    要跟踪时刻,请使用 Instant(始终采用 UTC)、OffsetDateTime(与 UTC 有偏移的时刻)或 ZonedDateTime(在特定区域看到的时刻)。

    奇怪的是,JDBC 4.2 需要支持 OffsetDateTime,但保留了最常见的两个类,InstantZonedDateTime,可选。

    因此,要捕获 UTC 中的当前时刻以进行 JDBC 工作:

    OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
    

    或者更长的:

    Instant instant = instant.now() ;  // Capture current moment in UTC.
    OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
    

    发送到数据库:

    myPreparedStatement.setObject( … , odt ) ;
    

    从数据库中检索:

    OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
    

    JPA

    我不使用JPA。但看起来这个问题已经涵盖了,JPA Storing OffsetDateTime with ZoneOffset。并看到这篇文章,What’s new in JPA 2.2 – Java 8 Date and Time Types

    其他时区和时差

    唯一的问题是在数据库中它正在保存 UTC 时间但提到了 MST

    This documentation for Oracle Database 似乎说 TIMESTAMP WITH TIME ZONE 类型确实记录了传入数据的时区或与 UTC 的偏移量。其他一些数据库,如 Postgres 将传入的值调整为 UTC(零时分秒的偏移量)。

    要获取 UTC,如上所示检索 OffsetDateTime,并调用 toInstant 方法以生成始终采用 UTC 的 Instant 对象。或者生成另一个OffsetDateTime,肯定是UTC:

    OffsetDateTime odtUtc = odt.withOffsetSameInstant​( ZoneOffset.UTC ) ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-30
      • 2014-01-27
      • 2017-10-05
      • 1970-01-01
      • 1970-01-01
      • 2012-01-27
      相关资源
      最近更新 更多