22

I'm experiencing a very weird behaviour while saving dates on database. On my (Linux centOS 6.2) server I use glassfish application server (3.1.1 - build 12) and Java (1.7.0_09), the application is developed in Java + GWT, and it uses PostgreSQL server (9.2.1). Inside the application there are several date fields that are saved on the db. The date fields use datepicker (http://code.google.com/p/gwt-datepicker, r30).

The date attribute of the db relation is date type (not timestamp). Some dates are saved a day before in the database. The problem happens only for dates between intervals, e.g. between 31.03.1968 and 27.10.1968, which makes me think some kind of summer time issue. But since it doesn't happen for 1969, for example, I cannot isolate the problem very well. I'm trying to find some other date interval inside which the problem happens. For example, if I select 19.05.1968 in the application, after saving in the database the date is saved as 18.05.1968.

The weird thing is that I have another istance of the same application on another server, and for the same dates they are saved correctly. This makes me think that the problem could rely either on:

  • glassfish configuration;
  • java (java.util.Date implementation?);
  • some kind of server configuration I'm missing

I tried to set to Europe/Rome (my timezone) every configuration possible of my server, but nothing. Any idea? How could I solve or investigate this problem?

UPDATE: 1968 was a leap year. The problem also happens in 1972, which is again a leap year. Summarizing: the "date-saved-one-day-before" problem happens in leap years during summer time date interval.

The code portion where the date oject is created is:

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

where dateField is declared as:

transient private DatePicker dateField;

The package is org.zenika.widget.client.datePicker.DatePicker (gwt-datepicker-r30 mentioned before), and DateTimeFormat refers to com.google.gwt.i18n.shared.DateTimeFormat

UPDATE after accepting the answer:

I used this workaround: when I create a date, I use the following code:

final long hours12 = 12L * 60L * 60L * 1000L;
Date d = new Date(d1.getTime() + hours12);
Lorenzo Marcon
  • 8,029
  • 5
  • 38
  • 63
  • what jre r u using? if it is 1.4 or prior then you might have an issue – MozenRath Nov 07 '12 at 09:35
  • 1
    java version "1.7.0_09" Java(TM) SE Runtime Environment (build 1.7.0_09-b05) Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode) – Lorenzo Marcon Nov 07 '12 at 09:47
  • @lorenzo.marcon maybe it was basically too long day yesterday for you ;) . But anyway that's interesting problem, and if you find a solution please let us know. – Adam Dyga Nov 07 '12 at 10:00
  • I removed the update from the question because I was wrong, I still experience the problem even this morning.. :/ – Lorenzo Marcon Nov 07 '12 at 10:02
  • Do you have code where you manipulate the Date? if so, can you post it? (I've seen many date calculations that break when a daylight saving change happens.) – richardtz Nov 07 '12 at 10:31
  • I updated my answer with the main piece of code, no other manipulation or calculations are done after that.. – Lorenzo Marcon Nov 07 '12 at 10:51
  • But day light saving calculation must crash the logic for every year... Not only for leap year... But still it would be convenient if we could see the code written for date manipulations. – Vishal Nov 07 '12 at 10:55
  • Set txtValue to display hours in addition to a date. Are your dates off by one hour? – Andrei Volgin Nov 07 '12 at 13:53
  • Can you trace/log the code path followed by the date value once it's been collected from the http request? – didierc Nov 07 '12 at 16:41
  • Daylight saving calculations are based on complex, constantly updating tables - and they do contain errors from time to time (maybe in this case only for your timezone?) They may also be different between Java and JavaScript. Since all of this can cause serious problems with DatePicker, the developers of GWT's built-in DataPicker chose to use the date at noon for safety (see the last few lines of `com.google.gwt.user.datepicker.client.CalendarUtil`) I assume, that "gwt-datepicker" doesn't? – Chris Lercher Nov 07 '12 at 18:30
  • I'm trying to put some logs to see where the date change happens. I'll let you know – Lorenzo Marcon Nov 07 '12 at 21:12

3 Answers3

9

Just set the time of the date to 12:00 (instead of the default 0:00) and you should be fine. The issue is that the GWT time zone library does not include all leap years from before 1990, and thus you will get a wrong time at the server (since the value is sent in the form of a timestamp and is one hour off).

By the way: GWT has a built-in date picker, see its demo at http://gwt.google.com/samples/Showcase/Showcase.html#!CwDatePicker

praseodym
  • 2,134
  • 15
  • 29
MikeN
  • 887
  • 5
  • 18
  • seems a viable solution, I'll check it out tonight, thanks. Where did you find the information about the lacking of leap years before 1990 in GWT? – Lorenzo Marcon Nov 08 '12 at 10:18
  • Well, not sure it's 1990, but you have to know more about the inner workings of GWT timezones. They are defined as transitions in the following file: http://code.google.com/searchframe#T04cSGC7sWI/trunk/user/src/com/google/gwt/i18n/client/constants/TimeZoneConstants.properties These transitions are in the format . Since the hour count is since 1970, there can't be any transitions before 1970. – MikeN Nov 08 '12 at 10:37
  • Looking at the file it seems all transitions from 1970 and up are defined (until 2037). – MikeN Nov 08 '12 at 10:46
  • well.. this worked to me. It's not really a fix, but as workaround worked well for my purposes, thanks. – Lorenzo Marcon Nov 09 '12 at 00:00
  • @lorenzo.marcon what was the cause? the missing transitions before 1970? – Adam Dyga Nov 09 '12 at 07:46
  • I'm not really sure where exactly the problem occurs, because I'm not the original author of the software, which is pretty complicated, and at the moment I don't have enough time to investigate the exact cause. I just shifted 12 hours forward in 4 points where a java.util.Date object was created, and it did the trick. If I get some time to find the right portion of code that caused the issue, I'll surely post the results – Lorenzo Marcon Nov 09 '12 at 08:56
  • I already said what the cause is: due to missing DST information in the GWT time zones, the timestamp will be one hour off during DST for dates before 1970. http://code.google.com/p/google-web-toolkit/issues/detail?id=6062 is the GWT bug report. – MikeN Nov 09 '12 at 09:42
1

Are you using java.util.date or java.sql. date (the latter is the correct one)? I had a similar problem with SQL Server, even if it was regular and yes, related with the summertime.

Basically, you store a Java date as midnight of a particular day. if summertime, the date get moved to the day before at 23:00, and then the time gets truncated! If you send the date with a "random" timestamp you will experience the problem one time out of 24 during the summer.

I don't remember exactly the solution (which will not help you directly as it refers to a different DBMS) but there was a setting in the dB to say "store the date as you receive it". You can test if this is the case by changing the dbcolumn to timestamp and looking at how the time get stored.

I did a bit of research - it seems the gwt-datepicker has a lot of issues! 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

I would not be surprised if their calculation had a bug on leap years. Also, it is entirely possible it is just a mismatch between what you are doing and what you think you are doing - working with Dates is a surprisingly difficult matter

To check, try:

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

And see if they match during summer on leap years. If it is a GWT bug, http://code.google.com/p/google-apps-script-issues/ is the right place to report it

thedayofcondor
  • 3,860
  • 1
  • 19
  • 28
  • thanks for the answer, I'm using both of them in different part of the code. The strange thing is that the issue happens only in leap years AND only in summer time date interval. I use postgreSQL: I tried to log all the queries, and the date is already wrong when it arrives to the db, so the problem is somewhere else. Today I'll try to simplify the code as much as possible to isolate the portion of code that causes the issue. – Lorenzo Marcon Nov 08 '12 at 08:56
0

Faced this issue in real time for date of birth.

I did the below fix, so that instead of saving a date at 12 am, date will be saved at 6 am which is before business hours of server. Even an hour is deducted, it won’t affect dob.

Calendar now = Calendar.getInstance();
now.setTime(YOUR_DATE);
now.set(Calendar.HOUR_OF_DAY, 6);
YOUR_DATE = now.getTime();

Mikes answer is fine. But, if we save with 12 pm, there is a possibility for error in date comparison, if user enters date during business hours before 12 pm.

user1242321
  • 1,578
  • 2
  • 18
  • 30
Sreejesh.K.R.
  • 73
  • 1
  • 9