首页 > 解决方案 > 日光节约的 JDBC Mysql 时区问题

问题描述

我在使用夏令时的日期字段的 MySql Select 语句时遇到问题。

原因:java.sql.SQLException:HOUR_OF_DAY:2 -> 3

唯一可行的解​​决方案是serverTimezone=GMT-6在 MySql 连接字符串中设置。但是当夏令时不存在时,我需要改变这一点。

如果我试图设置,serverTimezone=America/Denver那么它会给出同样的错误。

原因:java.sql.SQLException:HOUR_OF_DAY:2 -> 3

我的数据库时区是America/Denver

我的项目是带有 Java 8 和 Mybatis 的 Jersey 项目。

我尝试了多种建议的解决方案,但没有任何具体的工作。请指导我。

标签: javamysqltimezonejerseymybatis

解决方案


您应该TIMESTAMP在 MySQL 版本 8 中的类型列中跟踪数据库中的时刻。这种类型类似于 SQL 标准类型TIMESTAMP WITH TIME ZONE

使用 JDBC 4.2 或更高版本,与您的数据库交换java.time对象。

ZoneId z = ZoneId.of( "America/Denver" ) ;
LocalDate ld = LocalDate.of( 2020 , Month.JANUARY , 23 ) ;
LocalTime lt = LocalTime.of( 2 , 0 ) ;
ZonedDateTime zdt  = ZonedDateTime.of( ld , lt , z ) ;

该类ZonedDateTime会自动针对夏令时 (DST) 等异常情况进行调整。如果在某个日期的某个日期不存在凌晨 2 点,并且具有“提前春季”DST 转换,则将时间调整为凌晨 3 点。

奇怪的是,JDBC 4.2 需要支持OffsetDateTime但不支持更常用的InstantZonedDateTime. 所以转换。

myPreparedStatement.setObject( … , zdt.toOffsetDateTime() ) ;

恢复。

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
ZonedDateTime zdt = odt.withZoneSameInstant( z ) ;

请注意,使用这种方法意味着我们不关心服务器或客户端上的当前默认时区,也不关心会话中当前的默认时区。


推荐阅读