在Oracle Timestamp列中的UTC中保存日期

时间:2019-09-12 22:12:47

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

我需要将当前UTC日期和时间保存在TIMESTAMP WITH TIMEZONE类型的Oracle列中。这是来自使用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 class字段看起来像

@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(我的本地时区)作为时区。例如,保存的值为

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

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

19-SEP-19 09.50.53.820000000 PM UTC

如何通过Java 8类实现此Spring JPA?

谢谢

1 个答案:

答案 0 :(得分:3)

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

我不使用add Jenkins credentials with curl or Ansible。但是看来您已经涵盖了这个问题,JPA。并查看这篇帖子,JPA Storing OffsetDateTime with ZoneOffset

其他时区和偏移量

  

唯一的问题是在数据库中,它节省了UTC时间,但提到了MST

Oracle数据库的

What’s new in JPA 2.2 – Java 8 Date and Time Types似乎说TIMESTAMP WITH TIME ZONE类型确实记录了传入数据的时区或UTC偏移量。其他一些数据库,例如Postgres,会将传入的值调整为UTC(零小时-分钟-秒的偏移量)。

要获取UTC,请如上所述检索OffsetDateTime,然后调用toInstant方法来产生一个Instant对象,该对象始终位于UTC中。或产生另一个肯定是UTC的OffsetDateTime

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

This documentation