There is a very peculiar behaviour for PersistentLocalDate around the centuries. At those times, it seems to take the time zone into account, whereas LocalDate is supposed to ignore the time zone.
My problem appeared in the following situation:
I have a file containing dates, some of which are invalid. When they are invalid, they are replaced by 1900-01-01. When reading the file and saving the dates, everything seems ok.
Yet, when retrieving the dates from the database, I get 1899-12-31 instead, for the invalid dates.
(PersistentLocalDate uses new LocalDate(...) instead of LocalDate.fromDateFields(...) to convert the java.sql.Date into a LocalDate)
The following piece of code reproduces the issue without a database:
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Paris"));
testDates(0, 0, 1);
System.out.println("");
testDates(1, 0, 1);
System.out.println("");
testDates(-100, 0, 1);
}
private static void testDates(int yearFrom1900, int monthFromJanuary, int day) {
Date fromDataBase = new Date(yearFrom1900, monthFromJanuary, day);
LocalDate fromFile = new LocalDate(1900 + yearFrom1900, monthFromJanuary+1, day);
LocalDate convertedUsingConstructor = new LocalDate(fromDataBase);
LocalDate convertedUsingStatic = LocalDate.fromDateFields(fromDataBase);
System.out.println("fromFile = " + fromFile);
System.out.println("convertedUsingLocalDate = " + convertedUsingConstructor);
System.out.println("convertedUsingStatic = " + convertedUsingStatic);
}
The output of the program is:
fromFile = 1900-01-01
convertedUsingLocalDate = 1899-12-31
convertedUsingStatic = 1900-01-01
fromFile = 1901-01-01
convertedUsingLocalDate = 1901-01-01
convertedUsingStatic = 1901-01-01
fromFile = 1800-01-01
convertedUsingLocalDate = 1799-12-31
convertedUsingStatic = 1800-01-01
Last week I ran into the same problem. Seems to be an discrepancy in how java.util.Date and LocalDate handle leap seconds/minutes. More exactly: '1885-01-01' gives a java.util.Date object representing '1885-01-01T00:06:32.000'. This is saved in the database as '1885-01-01'. Reading from the database gives a Date object '1885-01-01 00:00:00.000'. Conversion to LocalDate gives the same discrepancy of 6 minutes 32 seconds: '1884-12-31T23:53:28.000'.
Here is a simple JUnit test to test this:
To nobody, your problem is because java.util.Date contains a time zone, the zone that your machine runs on. This has an offset of 6 mins 32 in 1885. So, although you think that the date in your database is '1885-01-01 00:00:00.000' it actually represents a millisecond value with a built in offset.
LocalDate.fromDateFields() may yield the answer you want.
To Frederic, I think that the same explanation applies. The question is whether PersistentLocalDate should use LocalDate.fromDateFields() or not. Have you tried changing the Joda code to do that?
@scolebourne
I haven't had the time yet, but this issue starting to be very annoying for us, I'm likely to subclass PersistentLocalDate to change that behaviour.
I'm not a time expert, so I can't tell if this should be the default behaviour for everybody, but, in our case, it is.
This the alternative code that we use:
public class PersistentLocalDateModified extends PersistentLocalDate {
}
This is far from an elegant solution, but playing with the seconds/minutes leap and so on was becoming slightly complex.