我正尝试在MySql表名person和列名regdate中插入一个日期值,数据类型为datetime。我正在设置一个值,例如'2019-08-21 20:25:20‘,但在保存+5:30小时后添加,并存储的值是'2019-08-22 03:55:20’。使用下面的Java代码生成日期值
Timestamp curDate = Timestamp.valueOf(Instant.now().atZone(ZoneId.of("Asia/Kolkata")).toLocalDateTime());然后在插入查询中使用.setTimestamp(1, curdate);。
我已检查MySql的时区是否设置为IST (GMT+0530)。App Server时区也设置为IST。但我不能理解为什么即使我明确地设置了日期值,+5:30小时也会增加。
我曾尝试将连接字符串中的时区设置为?serverTimezone=Asia/Kolkata,但不起作用。
但如果我使用本地机器连接相同的MySql实例来运行相同的代码,则不会出现任何问题,并且无需额外的5:30小时即可存储相同的值。我检查了App Server时区,它是IST。
MySql版本- 5.7.17-log mysql-connector-java - 8.0.15
我是不是遗漏了什么?
发布于 2019-08-22 02:48:42
您在这里有一些问题。
避免遗留的日期-时间类
首先,您正在将糟糕的遗留日期-时间类(java.sql.Timestamp)与现代java.time类混合在一起。不要,只使用java.time包中的类。
LocalDateTime不能代表某个时刻
您正在使用LocalDateTime跟踪某个时刻,但它不能。根据定义,该类不表示时间线上的点。该类有日期和时间,但故意缺少时区或从UTC偏移的上下文。调用toLocalDateTime会剥离有关区域/偏移的重要信息。
工具的谎言
您可能会对许多工具在生成文本以表示从数据库检索的日期-时间值时动态应用时区的善意但不幸的行为感到困惑。您可以通过使用Java & JDBC从数据库中获取纯正的值来避免这种情况。
TIMESTAMP WITH TIME ZONE
您未能在数据库中公开列的确切数据类型。如果您正在尝试跟踪某个时刻,请使用类似于SQL标准类型TIMESTAMP WITH TIME ZONE的数据类型。根据this doc的说法,在MySQL 8中,这显然是TIMESTAMP类型。(我是Postgres的用户,不是MySQL用户。)
在JDBC4.2和更高版本中,我们可以与数据库交换java.time对象。所以不需要再过多地接触java.sql.Timestamp了。
不幸的是,JDBC规范奇怪地选择了不需要支持Instant (在UTC) nor forZonedDateTime(a moment as seen in some particular time zone). The spec does require support for [OffsetDateTime`]2.中的片刻
提示:大部分时间学习在UTC中工作。仅当业务逻辑需要或为了向用户显示时,才调整为时区。
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ; // Capture current moment in UTC.通过准备好的语句写入数据库。
myPreparedStatement.setObject( … , odt ) ;检索。
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;通过某个特定地区(时区)的人们使用的挂钟时间来查看该时刻。
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

https://stackoverflow.com/questions/57596768
复制相似问题