我有一个JDBC Date列,如果ai使用getDate只获得' date '部分 2009年10月2日但是如果我使用getTimestamp我会得到满的' date ' 2009年10月2日13:56:78:890 。这是我想要的。
然而,getTimestamp返回的'date'会忽略'GMT值,假设为date; 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答案 0 :(得分:12)
这就是MySQL中Timestamp和其他时态类型之间的区别。时间戳以UTC时间整数保存为UTC,但其他类型按字面顺序存储日期/时间而不包含区域信息。
当您调用getTimestamp()时,如果类型为timestamp,则MySQL JDBC驱动程序会将时间从GMT转换为默认时区。它不会对其他类型执行此类转换。
您可以更改列类型或自行进行转换。我推荐以前的做法。
答案 1 :(得分:4)
您应该知道java.util.Date
(以及java.sql.Date
和java.sql.Timestamp
是java.util.Date
的子类)对时区一无所知,或者更确切地说,它们是始终是UTC。
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);
答案 2 :(得分:3)
前几天我遇到了一个类似的问题,从某些日期开始截断时间组件。
我们将其缩小到Oracle驱动程序版本的差异。
在Oracle的常见问题解答中,有一节关于此:
select sysdate from dual; ...while(rs.next())
在9201之前,这将返回: getObject for sysdate:java.sql.Timestamp<<<< getDate for sysdate:java.sql.Date sysdate的getTimetamp:java.sql.Timestamp
从9201开始,将返回以下内容
用于sysdate的getObject:java.sql.Date<<<<< getDate for sysdate:java.sql.Date>>没变 sysdate的getTimetamp:java.sql.Timestamp>>没有变化
注意:java.sql.Date没有时间部分,而java.sql.Timestamp则没有。
在数据类型映射中进行此更改时,当JDBC驱动程序从8i / 9iR1升级到920x JBDC驱动程序时,某些应用程序将失败和/或生成不正确的结果。 为了保持兼容性并在升级后保持应用程序正常工作,提供了兼容性标志。开发人员现在有一些选择:
默认情况下,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而不是连接属性,可以使用以下系统属性: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是TRUNCATED !!。
第二种解决方案对我来说非常简单 - 只需用getTimestamp替换getDate就可以了。我想这是一个坏习惯。
答案 3 :(得分:0)
从这个post我得出结论,JDBC确实检索了时间戳的时区(我不认为MS SQL支持这一点,大多数Google结果都指向Oracle)
当调用JDBC getTimeStamp方法时,它只获取 '毫秒 '部分并使用服务器TimeZone创建Date对象,是GMT。
当这个Date对象呈现给我的客户端+2 GMT时,它会增加2小时,这是标准偏移量,这会导致额外的小时数。
我已经通过删除我检索日期的时间偏移来校正这一点,即转换为真正的GMT日期。
答案 4 :(得分: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);
}