我想知道转换是如何工作的。 MySQL服务器(5.6)将TIMESTAMP视为区域调整(并在内部存储在/从UTC检索)。它还将DATETIME视为没有区域。
在Java方面,我建议在任何一种情况下都阅读java.sql.Timestamp
。是否存在从MySQL的DATETIME到java.sql.Timestamp
(例如应用客户端系统区域)的区域类型转换(当通过MySQL连接器5.1.37时)?
最后,我的服务器和客户端只有一个区域,因此我维护一个特定的ZoneId(在应用程序代码中)以转到ZonedDateTime
。但我想与ZonedDateTime
一起工作,来回存储为DATETIME存储的数据库。一个简单的转换示例将不胜感激!
答案 0 :(得分:1)
让我们解决您遇到的每个问题。首先:
是否存在从MySQL的DATETIME到java.sql.Timestamp
的区域类型转换(当通过MySQL-connector 5.1.37时)(例如应用客户端系统)区)?
首先,我假设您正在使用连接器中的getTimestamp(int)方法。我找不到能给我一个启发性答案的官方消息来源;然而,有一个问题,其中answer声明:当你调用getTimestamp()时,如果类型是时间戳,MySQL JDBC驱动程序将时间从GMT转换为默认时区。它不会对其他类型执行此类转换。但是,在this版本的方法中,如果底层数据库没有存储时间,它会使用基础
Calendar
将Timestamp
转换为指定的TimeZone
区域信息。这可能是您的第二个问题的解决方案,只要您知道存储该值的时区(您执行此操作)。但如果不是,似乎第一种方法没有发生转换,至少在它检索DATETIME
时。说到你的第二个问题:但是我想和ZonedDateTime
一起工作,来回存储为DATETIME的数据库。
只要您知道从哪个时区转换,我就会认为有一种方法可以做到这一点。正如我们之前所说,您和您的客户只使用一个ZoneId
,这完全没问题。但是,提供此答案是为了处理更多时区。如果要在数据库中存储连接的ZoneId
,则可以实现多个ZoneId
;检索它以及DATETIME
并最终将这些值处理为ZonedDateTime
。您可以使用ZoneId
类的the ID's将ZoneId
存储到数据库中(如果您愿意)。
Timestamp t = resultSet.getTimestamp(timestampColumnId);
ZoneId zoneId = ZoneId.of(resultSet.getString(zoneColumnId), ZoneId.SHORT_IDS);
ZonedDateTime d = ZonedDateTime.ofInstant(t.toInstant(), zoneId);
或者,您可以将DATETIME
作为TIMESTAMP
存储在数据库中,ZZ Coder在上述答案中建议。但是,你可以使用你已经硬编码的ZoneId
:
Timestamp t = resultSet.getTimestamp(timestampColumnId);
ZonedDateTime d = ZonedDateTime.ofInstant(t.toInstant(), zoneId);
修改的
查看source code,使用getTimestamp(int, Calendar)
或setTimestamp(int, Timestamp, Calendar)
函数进行接听或设置通话时,会使用Calendar
的时区。但是,在TIMESTAMP
的某些情况下,如果未使用Calendar
,则JDBC会使用服务器的时区。根据原始海报,它有效(见下面的comment)。