MySQL DATETIME和TIMESTAMP到java.sql.Timestamp到ZonedDateTime

时间:2016-06-27 21:54:33

标签: java mysql datetime

我想知道转换是如何工作的。 MySQL服务器(5.6)将TIMESTAMP视为区域调整(并在内部存储在/从UTC检索)。它还将DATETIME视为没有区域。

在Java方面,我建议在任何一种情况下都阅读java.sql.Timestamp。是否存在从MySQL的DATETIME到java.sql.Timestamp(例如应用客户端系统区域)的区域类型转换(当通过MySQL连接器5.1.37时)?

最后,我的服务器和客户端只有一个区域,因此我维护一个特定的ZoneId(在应用程序代码中)以转到ZonedDateTime。但我想与ZonedDateTime一起工作,来回存储为DATETIME存储的数据库。一个简单的转换示例将不胜感激!

1 个答案:

答案 0 :(得分:1)

让我们解决您遇到的每个问题。首先:

是否存在从MySQL的DATETIME到java.sql.Timestamp的区域类型转换(当通过MySQL-connector 5.1.37时)(例如应用客户端系统)区)?
首先,我假设您正在使用连接器中的getTimestamp(int)方法。我找不到能给我一个启发性答案的官方消息来源;然而,有一个问题,其中answer声明:
当你调用getTimestamp()时,如果类型是时间戳,MySQL JDBC驱动程序将时间从GMT转换为默认时区。它不会对其他类型执行此类转换。
但是,在this版本的方法中,如果底层数据库没有存储时间,它会使用基础CalendarTimestamp转换为指定的TimeZone区域信息。这可能是您的第二个问题的解决方案,只要您知道存储该值的时区(您执行此操作)。但如果不是,似乎第一种方法没有发生转换,至少在它检索DATETIME时。说到你的第二个问题:
但是我想和ZonedDateTime一起工作,来回存储为DATETIME的数据库。
只要您知道从哪个时区转换,我就会认为有一种方法可以做到这一点。正如我们之前所说,您和您的客户只使用一个ZoneId,这完全没问题。但是,提供此答案是为了处理更多时区。如果要在数据库中存储连接的ZoneId,则可以实现多个ZoneId;检索它以及DATETIME并最终将这些值处理为ZonedDateTime。您可以使用ZoneId类的the ID'sZoneId存储到数据库中(如果您愿意)。

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