It seems like DateTime does not initialize itself with correct date when we construct it from a java.util.Date with year 0001.
import java.time.LocalDateTime;
import java.util.TimeZone;
public class TestMain {
public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
java.util.Date d = new java.util.Date(-62135640000000L);
java.time.Instant i = java.time.Instant.ofEpochMilli(-62135640000000L);
System.out.println("d = new java.util.Date(-62135640000000L) : " new java.util.Date(-62135640000000L));
System.out.println("new org.joda.time.DateTime(d) : " new org.joda.time.DateTime(d));
System.out.println("new org.joda.time.DateTime(-62135640000000L) : " new org.joda.time.DateTime(-62135640000000L));
System.out.println("java.time.LocalDateTime.ofInstant(i, java.time.ZoneOffset.UTC): " LocalDateTime.ofInstant(i, java.time.ZoneOffset.UTC));
}
}
output:
d = new java.util.Date(-62135640000000L) : Sun Jan 02 12:00:00 UTC 1
new org.joda.time.DateTime(d) : 0000-12-31T12:00:00.000Z
new org.joda.time.DateTime(-62135640000000L) : 0000-12-31T12:00:00.000Z
java.time.LocalDateTime.ofInstant(i, java.time.ZoneOffset.UTC): 0000-12-31T12:00
Apart from the timezone related differences, if you note:
- the date is
02inDateobject and31inDateTime(or00if you change toUTC) - the year is
0001inDateobject and0000inDateTime
Am I doing something wrong, or is this a bug?
Did some more calculation
62135640000000 / 1000 / 3600 / 24 / 365.25 = 1968.9596167008898015058179329227
0.9596167008898015058179329227 * 365.25 = 350.5
365.25 - 350.5 = 14.75
So -62135640000000 = negative 1969 years and 350.5 days. Or about 14.75 days after start of year 0000.
CodePudding user response:
Not a bug: Julian vs. proleptic Gregorian calendar
This is no bug. It has been designed this way consciously. There are two different calendar systems in play here:
- The outdated
java.util.Dateclass uses the Julian Calendar for dates before 1582. It’s an attempt to reflect the calendar system that was actually in use in the greater parts of Europe back then. - Both Joda-Time and java.time use the ISO 8601 calendar system by default (other calendar systems are supported if you specify them explicitly). ISO 8601 in turn uses the proleptic Gregorian calendar. The proleptic Gregorian calendar is created by extrapolating the rules of the Gregorian calendar back into the times before the Gregorian calendar was invented and introduced. So it gives dates that do not agree with dates actually used back then, but in turn, are more well-defined.
The two calendars are several days apart for most dates, up to a couple of weeks as we get close to the Julian-Gregorian cross over in 1582 or later, depending on the jurisdiction.
Joda-Time supports the Gregorian/Julian calendar
The combined Gregorian/Juian calendar system that Date used is supported by Joda-TIme too through the GJChronology class.
DateTime dt = new DateTime(-62_135_640_000_000L,
GJChronology.getInstanceUTC());
System.out.println("DateTime with GJChronology: " dt);
Output:
DateTime with GJChronology: 0001-01-02T12:00:00.000Z
The year, the month, and the day-of-month all agree with what you got from Date.
Links
- ISO8601 Java calendar system on the Joda-Time website.
- Wikipedia article: ISO 8601
- Proleptic Gregorian calendar on Wikipedia
- Similar question: Java: How to get the timestamp of '1000-01-01 00:00:00' in UTC? The difference is that that question is about
ZonedDateTimefrom java.time, not about Joda-Time.
