JDBC时间戳和日期GMT问题

我有一个JDBC Date列,如果ai使用getDate只是在2009年10月2日获得’ date ‘部分,但是如果我使用getTimestamp我得到完整的’ date2009年10月2日13:56:78:890 。 这是我想要的。

但是,getTimestamp返回的’date’会忽略’GMT值,假设日期; 2009年10月2日13:56:78:890 ,我最终获得2009年10月2日15:56:78:890

我的日期在数据库中保存为+ 2GMT日期,但应用程序服务器在GMT上,即落后2小时

怎么还能按照现状,2009年10月2日13:56:78:890

编辑

我在客户端获得了GMT +2上的日期+2

这是MySQL中Timestamp和其他时间类型之间的区别。 时间戳以UTC时间_t保存为UTC,但其他类型按字面存储日期/时间而不包含区域信息。

当您调用getTimestamp()时,如果类型为时间戳,则MySQL JDBC驱动程序会将时间从GMT转换为默认时区。 它不会对其他类型执行此类转换。

您可以更改列类型或自行进行转换。 我推荐以前的做法。

您应该知道java.util.Date (以及java.sql.Datejava.sql.Timestamp ,它们是java.util.Date子类)对时区一无所知,或者说,它们始终在世界标准时间。

java.util.Date及其子类只不过是“自01-01-1970,UTC AM 12:00”以来的“毫秒数”容器。

要在特定时区中显示日期,请使用java.text.DateFormat对象将其转换为字符串。 通过调用setTimeZone()方法在该对象上设置时区。 例如:

 Date date = ...; // wherever you get this from DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // Make the date format show the date in CET (central European time) df.setTimeZone(TimeZone.getTimeZone("CET")); String text = df.format(date); 

前几天我遇到了类似的问题,其中时间组件从某些日期被截断。

我们将其缩小到Oracle驱动程序版本的差异。

在Oracle的常见问题解答中有一节关于此:


 select sysdate from dual; ...while(rs.next()) 

在9201之前,这将返回:getObject for sysdate:java.sql.Timestamp <<<< getDate for sysdate:java.sql.Date getTimetamp for sysdate:java.sql.Timestamp

从9201开始,将返回以下内容

getObject for sysdate:java.sql.Date <<<<< getDate for sysdate:java.sql.Date >> no change getTimetamp for sysdate:java.sql.Timestamp >> no change

注意:java.sql.Date没有时间部分,而java.sql.Timestamp没有。

随着数据类型映射的这种更改,当JDBC驱动程序从8i / 9iR1升级到920x JBDC驱动程序时,某些应用程序将失败和/或生成不正确的结果。 为了保持兼容性并在升级后保持应用程序正常工作,提供了兼容性标志。 开发人员现在有一些选择:

  1. 使用oracle.jdbc.V8Compatible标志。

默认情况下,JDBC驱动程序不检测数据库版本。 要更改用于处理TIMESTAMP数据类型的连接属性的兼容性标志

‘oracle.jdbc.V8Compatible’

可以设置为“true”,驱动程序的行为与8i,901x,9 200(相对于TIMESTAMPs)的行为相同。

默认情况下,标志设置为“false”。 在OracleConnection构造函数中,驱动程序获取服务器版本并相应地设置兼容性标志。

 java.util.Properties prop=newjava.util.Properties(); prop.put("oracle.jdbc.V8Compatible","true"); prop.put("user","scott"); prop.put("password","tiger"); String url="jdbc:oracle:thin:@host:port:sid"; Connection conn = DriverManager.getConnection(url,prop); 

使用JDBC 10.1.0.x而不是connection属性,可以使用以下系统属性:java -Doracle.jdbc.V8Compatible = true …..注意:此标志是一个仅限客户端的标志,用于控制时间戳和日期映射。 它不会影响任何数据库function。

“2。 在相应处理Date和TimeStamp列数据类型时,使用set / getDate和set / getTimestamp。

9i服务器支持Date和Timestamp列类型DATE映射到java.sql.Date,TIMESTAMP映射到java.sql.Timestamp。


所以对于我的情况,我有这样的代码:

 import java.util.Date; Date d = rs.getDate(1); 

使用9i我得到一个java.sql.Timestamp(这是java.util.Date的子类)所以一切都很常规,我有我的小时和分钟。

但是使用10g,相同的代码现在得到一个java.sql.Date(也是java.util.Date的子类,所以它仍然编译)但是HH:MM是TRUNCATED !!。

第二个解决方案对我来说非常简单 – 只需用getTimestamp替换getDate就可以了。 我想这是一个坏习惯。

从这篇文章我得出结论,JDBC确实检索了时间戳的时区(我不认为MS SQL支持这一点,大多数Google结果指向Oracle)

当调用JDBC getTimeStamp方法时,它只获取‘毫秒 ‘部分,并使用服务器TimeZone创建一个Date对象,即GMT。

当这个Date对象呈现给我的客户端+2 GMT时,它会增加2小时,这是标准偏移量,这会导致额外的小时数。

我通过从我检索的日期中删除时间偏移来校正这一点,即转换为真正的GMT日期。

 private Date convertDate(Date date1) throws ParseException { SimpleDateFormat sdfFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dateStr = sdfFormatter.format(date1); SimpleDateFormat sdfParser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); sdfParser.setTimeZone(TimeZone.getTimeZone("GMT")); return sdfParser.parse(dateStr); }