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
inDate
object and31
inDateTime
(or00
if you change toUTC
) - the year is
0001
inDate
object and0000
inDateTime
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:
- 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. - 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
ZonedDateTime
from java.time, not about Joda-Time.
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