Java JDBC:日期持续两天

Posted

技术标签:

【中文标题】Java JDBC:日期持续两天【英文标题】:Java JDBC: dates consistently two days off 【发布时间】:2012-07-03 00:58:18 【问题描述】:

我正在使用 Java JDBC 将日期写入 SQL Server 2008,然后将其读回。 回读的日期始终比实际写入的日期早两天。

我正在使用准备好的语句插入包含日期字段的行。日期值由以下提供:

java.sql.Date todaysDate = new java.sql.Date(System.currentTimeMillis()) ;
System.out.println(todaysDate.toString()) // -> 2012-07-02
ps.setDate(8, todaysDate);

将日期写入数据库后,如果我运行,SQL 服务器会显示正确的日期:

select date from table_name where date!=null // ->2012-07-02

如果我通过 JDBC 运行相同的查询,则使用

从结果集中检索日期值
java.sql.Date sqlDate = rs.getDate("date") ;
sqlDate.toString() // ->2012-06-30

插入的行是表中唯一具有非空日期的行,因此这似乎不是读取错误记录的情况。

我认为这将是一个众所周知的问题,但我可以通过 Google 搜索找到的关于“请假两天”问题的唯一参考没有明确的答案。

有什么想法吗?

beeky(生活在过去)

【问题讨论】:

如果你使用preparedStatement,不要从或转换成String。将日期(或时间戳)对象传递给 setDate。 服务器和客户端的时区是什么? 您确定这与 MM-DD-YYYY 与 DD-MM-YYYY 无关吗?如果您的日期往返于字符串,它们可以通过区域设置以有趣和意想不到的方式重新解释(在客户端运行时、数据库库和数据库代码中)。 @dystroy - 我正在使用 java.sql.Date obj 在准备好的 stmt 中设置值。你是不是想说相反的意思,例如使用字符串吗? 打印日期值的时间部分以查看确切的偏移量可能非常有趣。 【参考方案1】:

您的问题是时区值(“GMT”)。 您需要在您的JDBC 获取方法中引入此操作,如下所示:

Calendar gmt = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setDate(1, new Date(0)); // I assume this is always GMT
ResultSet rs = stmt.executeQuery();
rs.next();

//This will output 0 as expected
System.out.println(rs.getDate(1, gmt).getTime());

【讨论】:

TZ 会如何造成两天的差异?我可以在国际日期变更线附近看到一天,但是两天? 迈克,你的例子是回答我的问题还是演示如何查看时区偏移? 迈克,是的,我试过了,但老实说,我不明白你的例子,所以我可能做错了。 new java.sql.Date(0) 生成了 year=1969 的日期。之后,我就没有再追究了。如果 year=1969 告诉你我做错了什么,请纠正我。【参考方案2】:

错误的 JDBC 驱动程序

原来问题出在 MS JDBC 驱动程序上。我尝试了日期类型和日期转换的所有可能组合,但没有任何效果。经过大量搜索(应该先这样做!)我看到an older SO entry 上的评论暗示问题出在 Microsoft 的版本 3 JDBC 驱动程序上。我得到了最新的驱动程序,版本 4.something,问题就消失了。

感谢所有试图提供帮助的人。特别感谢 Mike 抽出时间发布解决方案。

-=beeky

【讨论】:

这很有趣,但我对 Microsft JSBC 4 friver 也有同样的问题,JTDS 工作正常 从 jdbc 4.0 升级到 4.1 并解决了上述问题。 JRE7 版本。 我已经尝试了几种不同的 MSSQL jdbc 驱动程序的多个版本,它们都通过 JDBC 与 SQL Server 2016 的行为相同,它们中的每一个都返回一个 getDate 或 getTimestamp 或者从一个日期、日期时间返回一个 getString或 datetime2(7) 列 2 天后插入的值。【参考方案3】:

我遇到了完全相同的问题。一旦我使用 java 6 运行时环境而不是 java 7 运行时环境,2 天的偏移就消失了。

所以这也可能是 JDBC 4.1 版本向后兼容 JDBC 3 驱动程序之间的差异。

【讨论】:

【参考方案4】:

我最近遇到过几次这个问题,在记住如果字段是 date 类型时会发生这种情况,将字段类型切换为 datetime 类型可以解决问题。

【讨论】:

【参考方案5】:

就像 user903724 所说的那样,更改为可以修复的版本 4,但在我的情况下,当我使用 sqljdbc4-3.0.jar 时,此问题仍然存在,但我将其更改为 sqljdbc42.jar,此问题得到了固定的。希望我的经验会有所帮助。 从sqljdbc42.jar下载

【讨论】:

【参考方案6】:

即使在 Java 8 中使用 sqljdbc4,我也遇到了同样的问题。

一旦我不需要此字段来在应用程序中进行任何类型的比较,我就通过在查询中转换字段来解决问题:CAST(dbo.tblPwActividadeParticipanteDetalhe.Data AS VARCHAR(10))

【讨论】:

【参考方案7】:

对于那些正在使用 maven 的人,请将此用于 java 8:

 <dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <version>6.2.1.jre8</version>
 </dependency>

如前所述,如果您使用旧版本,您可能会遇到这个问题,并且不容易调试。

【讨论】:

作为一个次要事实(驱动程序版本号)增强预先存在的答案,似乎这应该作为评论或对其他答案的编辑发布。【参考方案8】:

当我们在 Microsoft sql 中使用日期数据类型时,就会出现这个问题。我已修复此问题以将日期更改为日期时间。

【讨论】:

【参考方案9】:

如果您使用的是 MSSQL 2015,请使用此 Sqljdbc41 来解决此问题

 <!-- https://mvnrepository.com/artifact/com.microsoft.sqlserver/sqljdbc41 -->
<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>sqljdbc41</artifactId>
    <version>6.0.8112</version>
</dependency>

【讨论】:

以上是关于Java JDBC:日期持续两天的主要内容,如果未能解决你的问题,请参考以下文章

如何找出给定日期和开始和结束时间可用的所有持续时间:java

两个日期之间的持续时间Java [重复]

如何在java中找到两个日期之间的差异持续时间?

java-JDBC从数据库中读取数据并进行日期民族男女的转换

日历的日期对象 [Java]

笔记之_Java的JDBC整理