Mysql服务器比操作系统时间节省了3个小时,从而节省了LocalDateTime

时间:2019-05-04 15:36:07

标签: java mysql spring-boot spring-data-jpa

在服务过程中,在我的情况下,在使用Java 8的Spring Boot API中,在将LocaDateTime写入数据库的过程中,在数据库侧保存配置为TIMESTAMP的属性,在API中保存配置为LocaDateTime的属性时,该日期是保存时间比当前操作系统日期晚3个小时。

假设我尝试在上午10点准确地执行此操作,保存到数据库的日期应该是11个小时,但就我而言,它不能以这种方式工作...

private LocalDateTime dataLimite;

@PrePersist
public void prepareToSave() {
    String str = "1986-04-08 10:00";
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    LocalDateTime dateTime = LocalDateTime.parse(str, formatter);
    this.dataLimite = dateTime.plusHours(1);
}

Date into the database 显然应该指出,这是Mysql配置方面的问题,但是当我测试...

SELECT NOW();

结果恰好是操作系统的日期和时间,那么到底发生了什么真正的问题?如何解决此问题?

1 个答案:

答案 0 :(得分:1)

LocalDateTime

仔细阅读文档。

  

此类不存储也不表示时区。相反,它是对用于生日的日期的描述,以及在墙上时钟上看到的本地时间。如果没有其他信息(例如偏移量或时区),则无法在时间轴上表示时刻。

Java中的LocalDateTime类不能用于表示时刻。它代表了大约26-27小时(全球时区范围)内的潜在时刻。

此类包含日期和时间,但故意缺少时区或UTC偏移量的任何概念。因此,例如,如果您存储例如今年1月23日中午,那么我们就不知道您是否要在东京,加尔各答,巴黎或蒙特利尔中午……所有不同的时刻,相隔数小时,发生在东部的较早时间,以及稍后发生的西方。

所以您使用的是错误的类。请暂时使用InstantOffsetDateTimeZonedDateTime

TIMESTAMP

更仔细地阅读文档。

MySQL 8中的TIMESTAMP类型类似于SQL标准类型TIMESTAMP WITH TIME ZONE。此类型表示时刻,即时间轴上的特定点。

将提交到数据库的时刻调整为UTC的文档explains已存储。

  

MySQL将TIMESTAMP值从当前时区转换为UTC进行存储,然后从UTC返回当前时区进行检索。

这说明了您的问题。您隐式依赖当前的默认时区来分配给Java中缺少任何时区的错误类型的对象。 切勿编写依赖于服务器当前默认时区(或语言环境)的代码,因为这超出了程序员的控制范围。相反,请始终明确指定所需/期望的时区。或者更好,只要有可能就在UTC中工作。

为获得最佳结果,与数据库交换值时请坚持使用UTC。

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

myPreparedStatement.setObject( … , odt ) ;

检索。

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

要查看特定地区人民使用的挂钟时间的那一刻,请应用ZoneId以获得ZonedDateTime

ZoneId z = ZoneId.of( "Australia/Sydney" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

Table of date-time types in Java (both modern and legacy) and in standard SQL.