在服务过程中,在我的情况下,在使用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);
}


java - Mysql服务器将LocalDateTime与OS时间相比节省了3个小时-LMLPHP
显然应该指出,这是Mysql配置方面的问题,但是当我测试时...

SELECT NOW();


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

最佳答案

LocalDateTime

仔细阅读文档。


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


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

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

因此,您使用了错误的类。暂时使用InstantOffsetDateTimeZonedDateTime

TIMESTAMP

请更仔细地阅读文档。

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

将提交给数据库的文档explains调整为UTC进行存储。


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


java - Mysql服务器将LocalDateTime与OS时间相比节省了3个小时-LMLPHP

09-10 02:54
查看更多