Home > Enterprise >  Is this a bug in joda time? Handling very old (year 0000) instant / negative epoch
Is this a bug in joda time? Handling very old (year 0000) instant / negative epoch

Time:10-16

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 02 in Date object and 31 in DateTime (or 00 if you change to UTC)
  • the year is 0001 in Date object and 0000 in DateTime

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:

  1. The outdated java.util.Date class 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.
  2. 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

  • Related