i’m having a problem while converting Timestamp objects to joda’s LocalTime.
See example below:
public static void main(String[] args) {
Timestamp t = Timestamp.valueOf("1111-11-11 00:00:00");
System.out.println(t); //-- prints '1111-11-11 00:00:00.0'
System.out.println(new LocalDate(t)); //-- prints '1111-11-17'
Calendar calendar = Calendar.getInstance();
calendar.setTime(t);
System.out.println(LocalDate.fromCalendarFields(calendar)); //-- prints '1111-11-11'
}
I could not determine why ‘new LocalDate(t)’ results in ‘1111-11-17’. Can anyone help me on that?
I notice this “problem” while using joda-time-hibernate to populate my bean’s property of type LocalDate.
This indeed has to do with the different types of calendars.
java.sql.Timestamp, likejava.util.Date, don’t have any calendar information, as they are stored solely as a number, the number of milliseconds since 1970, with the implied assumption that there was a jump between October 4 and October 15 1582, when the Gregorian calendar was officially adopted, replacing the old Julian calendar. So, you can’t possibly have a Date (or Timestamp) object representing October 7, 1582. If you try to create such a date, you’ll automatically end up 10 days later. For example:In other words, Date objects have an implied Julian+Gregorian chronology, automatically switching between those two.
JodaTime is a bit smarter, it supports several Chronologies, including a continuing Julian, a proleptic Gregorian, a mixed Julian+Gregorian, and a standard ISO Chronology which is almost identical to the Gregorian one. If you read the JavaDoc of the
LocalDate.fromCalendarFieldsmethod, you’ll see that it mentions that:The mixed Julian+Gregorian chronology behaves like the implicit Java dates, with an automatic switch between the two different calendars. The pure chronologies assume that their calendar system is forever in use, so for example it assumes that the Gregorian calendar has been used since the start of time.
Let’s see how each Chronology treats the 1111-11-11 date:
Ends up as:
As you can see, the two modern chronologies (ISO and Gregorian) report the correct date if they would have been in use since from the start, while the two that use the Julian calendar report the date as it was known back then, although in hindsight we know it to be off by 7 days compared to the true equinox date.
Let’s see what happened around the switch:
ends up as:
So the only one that’s left behind is the Julian calendar. That was a valid date in all the countries that didn’t accept the Gregorian calendar yet, which back then was a lot of countries. Greece made the switch in 1923…
One millisecond before that, the date was:
Meaning:
The ISO and Gregorian chronologies report a date that didn’t actually exist in the Gregorian calendar, since there was no Gregorian calendar before October 15, yet this date is valid in an extended, proleptic Gregorian calendar. It’s like finding a BCE date inscribed on a BCE monument… Nobody knew that they were before Christ before Christ was even born.
So, the root of the problem is that a date string is ambiguous, since you don’t know in which calendar you’re measuring. Is the year 5772 a year in the future, or is it the current Hebrew year? Java assumes a mixed Julian+Gregorian calendar. JodaTime provides extensive support for different calendars, and by default it assumes the ISO8601 chronology. Your date is automatically converted from the Julian calendar in use in 1111 to the ISO chronology that we currently use. If you want your JodaTime-enhanced timestamps to use the same chronology as the
java.sql.Timestampclass, then explicitly select theGJChronologywhen constructing JodaTime objects.