8

我有一个 JDBC 日期列,如果 ai 使用 getDate仅在2009 年 10 月 2 日获得“日期”部分,但如果我使用 getTimestamp,我将获得完整的“日期2009 年 10 月 2 日 13:56:78:890。这正是我想要的。

但是,getTimestamp 返回的“日期”“忽略”了 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

4

5 回答 5

13

这就是 Timestamp 和 MySQL 中其他时间类型的区别。时间戳在 UTC 中保存为 Unix time_t,但其他类型在没有区域信息的情况下按字面意思存储日期/时间。

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

您可以更改列类型或自己进行转换。我推荐前一种方法。

于 2009-10-02T12:13:46.867 回答
4

您应该知道java.util.Date(以及java.sql.Dateand java.sql.Timestamp,它们是 的子类java.util.Date)对时区一无所知,或者更确切地说,它们始终使用 UTC。

java.util.Date它的子类只不过是一个“自 1970 年 1 月 1 日凌晨 12:00 UTC 以来的毫秒数”值的容器。

要在特定时区显示日期,请使用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);
于 2009-10-02T12:05:56.697 回答
3

前几天我遇到了一个类似的问题,时间部分从某些日期被截断。

我们将其缩小到 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 >> 没有变化 getTimetamp for sysdate :java.sql.Timestamp >> 没有变化

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

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

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

JDBC Driver 默认不检测数据库版本。要更改处理 TIMESTAMP 数据类型的兼容性标志,连接属性

'oracle.jdbc.V8 兼容'

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

默认情况下,该标志设置为“假”。在 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 中,可以使用以下系统属性代替连接属性: java -Doracle.jdbc.V8Compatible=true .....注意:此标志是一个仅限客户端的标志,用于管理时间戳和日期映射。它不会影响任何数据库功能。

'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 被截断了!!。

第二种解决方案对我来说非常简单 - 只需将 getDate 替换为 getTimestamp 就可以了。我想那是个坏习惯。

于 2009-10-21T20:51:28.957 回答
0

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

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

当这个 Date 对象呈现给我的客户(格林威治标准时间 +2)时,它会增加 2 小时,这是导致额外小时数的标准偏移量。

我已经通过删除我检索到的日期的时间偏移来纠正这个问题,即转换为真正的 GMT 日期。

于 2009-10-02T14:59:58.473 回答
0
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);
    }
于 2013-03-09T13:33:12.163 回答