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

Time:10-14

It seems like DateTime does not initialize itself with incorrect 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

This is no bug. It has been consciously designed this way. There are two different calendar systems in play here:

  1. The outdated java.util.Date class uses the Julian Calendar for dates before 1583. 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

CodePudding user response:

If you are using at least Java 8, then it is recommended to use its date-time API. It is even recommended on Joda-Time Web site.

Simply create an Instant object and convert it to a LocalDateTime.

java.time.Instant instant = java.time.Instant.ofEpochMilli(-62135640000000L);
java.time.LocalDateTime ldt = java.time.LocalDateTime.ofInstant(instant, java.time.ZoneOffset.UTC);
System.out.println(ldt);

The above code prints the following:

0000-12-31T12:00

In other words, December 31 in year 0 (zero) at 12 noon.

If you want a different format, you can use class DateTimeFormatter

  • Related