在将Java Date写入SQL TIMESTAMP列之前,JDBC是否将日期从JVM时区转换为数据库会话时区?

Der*_*har 26 java sql timezone timestamp jdbc

在将Java Date写入SQL TIMESTAMP列之前,JDBC是否将日期从Java虚拟机时区转换为数据库会话的日期?

例如,假设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'

Buh*_*ndi 14

不,JDBC只是客户端如何访问数据库的API.对于时间戳存储,这必须由编写符合JDBC API标准的数据库驱动程序的组织所依赖.

是MySQL实现一个实现PreparedStatement.他们似乎将Java的JVM时区带到MySQL Timezone(检查setTimestampInternal()方法).

  • 相比之下,`setTimestamp()`的PostgresQL JDBC驱动程序实现使用JVM时区转换给定日期.请参阅http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/jdbc/pgjdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java?rev=1.118中的方法`AbstractJdbc2Statement #setTimestamp(int,Timestamp,Calendar)`. &content-type = text/x-cvsweb-markup和`TimestampUtils#toString(Calendar,Timestamp)`,网址为http://cvs.pgfoundry.org/cgi-bin/cvsweb.cgi/jdbc/pgjdbc/org/postgresql/jdbc2 /TimestampUtils.java?rev=1.23&content-type=text/x-cvsweb-markup.时区处理依赖于JDBC驱动程序! (4认同)
  • 是的你是对的。从 MySQL JDBC 驱动程序实现中可以清楚地看出,`setTimestampInternal()` 将给定日期转换为服务器时区 (`x = TimeUtil.changeTimezone(this.connection, x, tz, 2059 this.connection.getServerTimezone()); `)。它还使用依赖于语言环境的“SimpleDateFormat”将日期格式化为字符串。 (2认同)

Jag*_*gat 7

现在我的要求是它应该以GMT/UTC存储值,而不管JVM的时区.有没有办法在运行时设置时区,然后在完成JDBC后取消设置时区?

编辑:好的,我找到了解决这个问题的方法.做了以下

TimeZone default = TimeZone.getDefault();
try
{
  TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

  //Do stuff with JDBC
}
finally
{
  TimeZone.setDefault(default);
}
Run Code Online (Sandbox Code Playgroud)

  • **小心**[更改默认值](http://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html#setDefault-java.util.TimeZone-)时区有风险商业.此更改*会影响在此JVM中运行的所有线程*中的所有代码,而不仅仅是方法中的本地代码. (5认同)
  • 如果其他线程在日期同时进行计算,假设默认时区不是UTC,则可能会导致竞争条件. (4认同)