在将 Java 日期写入 SQL TIMESTAMP 列之前,JDBC 是否将日期从 JVM 时区转换为数据库会话时区?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4123534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Before writing a Java Date to an SQL TIMESTAMP column, does JDBC translate the date from the JVM time zone to the database session time zone?
提问by Derek Mahar
Before writing a Java Dateto an SQL TIMESTAMPcolumn, does JDBCtranslate the date from the Java virtual machine time zone to that of the database session?
在将 Java日期写入SQL TIMESTAMP列之前,JDBC 是否将日期从 Java 虚拟机时区转换为数据库会话的日期?
For example, suppose the Java virtual machine time zone is UTCand the database session time zone is UTC-5. If a Java program attempts to store 2000-01-01 00:00:00
by passing it to PreparedStatement#setTimestamp(int, Timestamp)
, according to the JDBC standard, will the database store TIMESTAMP '2000-01-01 00:00:00'
or TIMESTAMP '1999-12-31 19:00:00'
?
例如,假设 Java 虚拟机时区是UTC并且数据库会话时区是UTC-5。如果 Java 程序尝试2000-01-01 00:00:00
通过将其传递给 来进行存储PreparedStatement#setTimestamp(int, Timestamp)
,根据 JDBC 标准,数据库将存储TIMESTAMP '2000-01-01 00:00:00'
还是TIMESTAMP '1999-12-31 19:00:00'
?
采纳答案by Buhake Sindi
No, JDBCis just an API on how the client can access the database. For timestamp storage, this will have to be dependent by the organisation that writes their database drivers that conforms to the JDBC API standard.
不,JDBC只是关于客户端如何访问数据库的 API。对于时间戳存储,这必须取决于编写符合 JDBC API 标准的数据库驱动程序的组织。
Here'san implementation of MySQL's implementation of PreparedStatement
. They seem to take Java's JVM timezone to MySQL Timezone (check the setTimestampInternal()
method).
这是 MySQL 的PreparedStatement
. 他们似乎将 Java 的 JVM 时区带到 MySQL 时区(检查setTimestampInternal()
方法)。
回答by Jagat
Now my requirement is that it should store the value in GMT/UTC irrespective of the timezone of the JVM. Is there a way to set the timezone on the fly and then to unset it once I'm done with JDBC?
现在我的要求是它应该以 GMT/UTC 格式存储值,而不管 JVM 的时区如何。有没有办法即时设置时区,然后在完成 JDBC 后取消设置?
Edit: Ok, I found a way around that issue. Did the following
编辑:好的,我找到了解决这个问题的方法。做了以下事情
TimeZone default = TimeZone.getDefault();
try
{
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
//Do stuff with JDBC
}
finally
{
TimeZone.setDefault(default);
}
回答by Diana Yashaev
You can use overloaded setTimestamp
setter accepting Calendar
instance to specify timezone
您可以使用重载的setTimestamp
setter 接受Calendar
实例来指定时区
Sample (If you're using Joda datetime):
示例(如果您使用的是 Joda 日期时间):
org.joda.time.DateTime sendDateUTC = new DateTime( DateTimeZone.UTC ).withMillis( millis );
statement.setTimestamp (1, sendDateUTC, sendDateUTC.toGregorianCalendar() );
As per javaDoc:
Sets the designated parameter to the given java.sql.Timestamp
value, using the given Calendar
object. The driver uses the Calendar
object to construct an SQL TIMESTAMP
value, which the driver then sends to the database. With a Calendar
object, the driver can calculate the timestamp taking into account a custom timezone. If no Calendar object is specified, the driver uses the default timezone, which is that of the virtual machine running the application.
根据 javaDoc:java.sql.Timestamp
使用给定Calendar
对象将指定参数设置为给定值。驱动程序使用该Calendar
对象构造一个SQL TIMESTAMP
值,然后驱动程序将其发送到数据库。使用Calendar
对象,驱动程序可以在考虑自定义时区的情况下计算时间戳。如果未指定日历对象,驱动程序将使用默认时区,即运行应用程序的虚拟机的时区。
void setTimestamp(int parameterIndex, java.sql.Timestamp x, Calendar cal)
throws SQLException;
回答by ChrisG65
The spec is goofy. The java.util.Date stores milliseconds from epoch in the GMT reference frame. Java.sql.Timestamp is a Date plus nanoseconds in the same reference frame. All the non-deprecated getters and setters use the GMT reference frame. For any sort of sanity, the default time zone for a storing a Timestamp should be GMT.
规范是愚蠢的。java.util.Date 在 GMT 参考系中存储从纪元开始的毫秒数。Java.sql.Timestamp 是同一参考系中的日期加纳秒。所有未弃用的 getter 和 setter 都使用 GMT 参考框架。对于任何类型的理智,存储时间戳的默认时区应该是 GMT。
In a multi-tiered application, the front-end, the driver, and the database server could all be in different time zones. Some of the tiers could be in different time zones at the same time; for instance, if you are doing internet load-balancing across a continent, or if you have a mobile app connecting to a central server. A cloud operating environment would be much the same scenario where you have no idea where the JDBC driver will be running, nor any guarantee that will never change.
在多层应用程序中,前端、驱动程序和数据库服务器都可能处于不同的时区。一些层级可能同时处于不同的时区;例如,如果您在一个大陆上进行互联网负载平衡,或者您有一个移动应用程序连接到中央服务器。云操作环境与您不知道 JDBC 驱动程序将在哪里运行,也不保证永远不会改变的情况大致相同。
The only way I know to achieve consistency in these environments is to only use the parameter setter and ResultSet getter that accept a Calendar, and make sure every app that accesses the data uses the some calender, preferrably GMT or UTC.
我知道在这些环境中实现一致性的唯一方法是只使用接受日历的参数设置器和 ResultSet 获取器,并确保每个访问数据的应用程序都使用一些日历,最好是 GMT 或 UTC。