Java - 保存为前一天的日期

2022-09-02 01:58:07

我在数据库上保存日期时遇到了一个非常奇怪的行为。在我的(Linux centOS 6.2)服务器上,我使用glassfish应用程序服务器(3.1.1 - build 12)和Java(1.7.0_09),该应用程序是用Java + GWT开发的,它使用PostgreSQL服务器(9.2.1)。在应用程序中,有几个日期字段保存在数据库中。日期字段使用日期选取器(http://code.google.com/p/gwt-datepicker,r30)。

数据库关系的日期属性是日期类型(不是时间戳)。某些日期在一天前保存在数据库中。这个问题只发生在间隔之间的日期,例如31.03.1968和27.10.1968之间,这让我想到了某种夏令时问题。但是,由于它不会发生在1969年,例如,我无法很好地隔离这个问题。我正在尝试查找出现问题的其他日期间隔。例如,如果我在应用程序中选择 19.05.1968,则在数据库中保存后,日期将另存为 18.05.1968。

奇怪的是,我在另一台服务器上有同一应用程序的另一个位置,并且在相同的日期,它们被正确保存。这让我认为这个问题可以依赖于:

  • 玻璃鱼配置;
  • java (java.util.Date implementation?);
  • 我缺少某种服务器配置

我试图将服务器的每个可能配置都设置为欧洲/罗马(我的时区),但什么都没有。有什么想法吗?如何解决或调查此问题?

更新:1968年是闰年。这个问题也发生在1972年,这又是一个闰年。总结:“保存日期前一天”问题发生在闰年夏季时间日期间隔内。

创建日期对象的代码部分是:

Date d = dateField.getSelectedDate();
if (d != null) {
    txtVal = DateTimeFormat.getFormat("dd/MM/yyyy").format(d);
}

其中 dateField 声明为:

transient private DatePicker dateField;

该软件包是(前面提到的gwt-datepicker-r30),DateTimeFormat指的是org.zenika.widget.client.datePicker.DatePickercom.google.gwt.i18n.shared.DateTimeFormat

接受答案后更新:

我使用了此解决方法:当我创建日期时,我使用以下代码:

final long hours12 = 12L * 60L * 60L * 1000L;
Date d = new Date(d1.getTime() + hours12);

答案 1

只需将日期的时间设置为12:00(而不是默认的0:00),您应该没问题。问题在于GWT时区库不包括1990年之前的所有闰年,因此您将在服务器上得到错误的时间(因为该值以时间戳的形式发送并且相差一小时)。

顺便说一句:GWT有一个内置的日期选择器,在 http://gwt.google.com/samples/Showcase/Showcase.html#!CwDatePicker


答案 2

您使用的是 java.util.date 还是 java.sql。日期(后者是正确的)?我在SQL Server上遇到了类似的问题,即使它是常规的,是的,与夏季有关。

基本上,您将Java日期存储为特定日期的午夜。如果是夏天,日期会移到前一天的23:00,然后时间就会被截断!如果您使用“随机”时间戳发送日期,您将在夏季的24次中遇到一次问题。

我不记得确切的解决方案(它不会直接帮助你,因为它指的是不同的DBMS),但是在dB中有一个设置说“在收到日期时存储日期”。您可以通过将 dbcolumn 更改为时间戳并查看时间的存储方式来测试是否属于这种情况。

我做了一些研究 - 似乎gwt-datepicker有很多问题!http://code.google.com/p/google-apps-script-issues/issues/detail?id=2022 http://code.google.com/p/google-apps-script-issues/issues/detail?id=2001

如果他们的计算在闰年有错误,我不会感到惊讶。此外,这完全有可能只是你正在做的事情和你认为你正在做的事情之间的不匹配 - 使用Date是一件令人惊讶的困难问题

要进行检查,请尝试:

final java.util.Date ud = dateField.getSelectedDate();;
final java.sql.Date sd = new java.sql.Date(ud.getTime());
System.out.println(ud);// this is what you pick from the DatePicker
System.out.println(sd);// this is what will be stored on the database

看看它们在闰年的夏季是否匹配。如果是 GWT 错误,http://code.google.com/p/google-apps-script-issues/ 是正确的报告位置