Java JDBC:日期一致休息两天

Java JDBC: dates consistently two days off

提问人:user903724 提问时间:7/2/2012 最后编辑:StackzOfZtuffuser903724 更新时间:5/24/2019 访问量:10327

问:

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

我正在插入包含带有预处理语句的 Date 字段的行。日期值由以下人员提供:

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

将日期写入数据库后,如果我运行以下命令,SQL Server 会向我显示正确的日期:

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

如果我通过JDBC运行相同的查询,则使用从结果集中检索日期值

java.sql.Date sqlDate = rs.getDate("date") ;
sqlDate.toString() // ->2012-06-30

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

我以为这将是一个众所周知的问题,但我在谷歌搜索中找到的唯一关于“休息两天”问题的参考资料没有明确的答案。

有什么想法吗?

Beeky(活在过去)

java sql-server 日期 jdbc

评论

0赞 Denys Séguret 7/2/2012
如果使用 preparedStatement,请不要从 String 转换或转换为 String。将日期(或时间戳)对象传递给 setDate。
0赞 Jim Garrison 7/3/2012
服务器和客户端的时区是什么?
0赞 Cade Roux 7/3/2012
你确定这与 MM-DD-YYYY 与 DD-MM-YYYY 无关吗?如果日期要与字符串往来,则可以通过区域设置以有趣且意想不到的方式(在客户端运行时、数据库库和数据库代码中)重新解释它们。
0赞 user903724 7/3/2012
@dystroy - 我正在使用 java.sql.Date obj 在准备好的 stmt 中设置值。你的意思是相反的,例如,Do use strings?
1赞 Jim Garrison 7/3/2012
打印日期值的时间部分以查看确切的偏移量可能非常有趣。

答:

0赞 GingerHead 7/2/2012 #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());

评论

0赞 Jim Garrison 7/3/2012
TZ将如何导致两天的差异?我可以在国际日期变更线附近看到一天,但两天呢?
0赞 user903724 7/4/2012
Mike,你的例子是回答我的问题,还是演示如何查看时区偏移量?
0赞 user903724 7/5/2012
迈克,是的,我试过了,但说实话,我不明白你的例子,所以我可能做错了。新的 java.sql.Date(0) 生成了一个日期,年份=1969。在那之后,我没有再追究它。如果 year=1969 告诉你我做错了什么,请纠正我。
22赞 user903724 7/12/2012 #2

JDBC驱动程序故障

事实证明,问题出在MS JDBC驱动程序上。我尝试了日期类型和日期转换的所有可能组合,但没有任何效果。经过大量的搜索(应该先这样做!我看到一个较旧的 SO 条目的评论,暗示问题是 Microsoft 的版本 3 JDBC 驱动程序。我得到了最新的驱动程序,版本 4.something,问题消失了。

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

-=哔

评论

0赞 Javasick 3/17/2017
这很有趣,但我对 Microsft JSBC 4 friver 也有同样的问题,JTDS 工作正常
0赞 PST 6/26/2019
从 jdbc 4.0 升级到 4.1,这解决了上述问题。JRE7 版本。
0赞 J E Carter II 3/4/2020
我尝试了几个不同 MSSQL jdbc 驱动程序的多个版本,它们都通过 JDBC 与 SQL Server 2016 的行为相同,每个驱动程序都从 date、datetime 或 datetime2(7) 列返回 getDate 或 getTimestamp 或 getString,距离插入的值还差 2 天。
0赞 GerritCap 8/27/2013 #3

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

因此,JDBC 版本 4.1 与 JDBC 3 驱动程序的向后兼容性也可能有所不同。

2赞 Bill Harrelson 5/11/2015 #4

我最近遇到过几次这个问题,在想起如果字段是日期类型时会发生这种情况之前,我的头发被扯掉了,将字段类型切换到日期时间类型可以解决问题。

2赞 Kun 4/11/2016 #5

就像 user903724 所说的那样,更改为将修复的版本 4,但就我而言,当我使用 sqljdbc4-3.0.jar 时,此问题仍然重现,但我将其更改为 sqljdbc42.jar,此问题已修复。希望我的经验对您有所帮助。 从 sqljdbc42.jar 下载

0赞 Edson Sousa 4/5/2017 #6

即使将 sqljdbc4 与 Java 8 一起使用,我也遇到了同样的问题。

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

5赞 Hasson 7/27/2017 #7

对于使用 maven 的用户,请在 java 8 中使用以下内容:

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

正如所指出的,如果使用旧版本,可能会遇到这个问题,并且不容易调试。

评论

0赞 Basil Bourque 7/28/2017
作为一个次要的事实点(驱动程序版本号)增强了预先存在的答案,似乎这应该作为评论或作为对其他答案的编辑发布。
1赞 Nirmal Kumar 4/12/2018 #8

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

2赞 Virudhai Paul 10/12/2018 #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>