5

I had a curious situation at work, where an application sent us XML containing the value "0001-01-01", which was parsed into an instance of XmlGregorianCalendar. I then realized, the value magically converted into "0001-01-03", the exact amount of 2 days was added.

This happened during the conversion from GregorianCalendar to Date, which I reproduced as followed:

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

public class Test {

    public static void main(String[] args) throws ParseException, DatatypeConfigurationException {
        final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

        GregorianCalendar gregCalendar = new GregorianCalendar();
        gregCalendar.setTime(dateFormat.parse("0001-01-01"));
        XMLGregorianCalendar calendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(gregCalendar);

        System.out.println("calendar: " + calendar);
        System.out.println("date: " + calendar.toGregorianCalendar().getTime());
    }
}

Sample output:

calendar: 0001-01-01T00:00:00.000Z
date: Mon Jan 03 00:00:00 GMT 1

The milliseconds differ by the exact amount of 172800000. Does anybody know why?

Makoto
  • 104,088
  • 27
  • 192
  • 230
John Doe
  • 59
  • 2
  • I added a sample output which was what I got when I ran it. Feel free to edit it if what you're seeing is different. – Michael Aug 22 '17 at 15:52
  • 1
    People WILL be seeing different things because of their timezones. Your zone is GMT so you see the output seen in the question. I am in EST so I get this output: calendar: 0001-01-01T00:00:00.000-05:00 date: Mon Jan 03 00:00:00 EST 1 – Coder Aug 22 '17 at 15:55
  • Related question https://stackoverflow.com/questions/6841333/why-is-subtracting-these-two-times-in-1927-giving-a-strange-result/6841479#6841479 – jontro Aug 22 '17 at 16:02
  • @jontro: This one isn't due to time zone differences. – Bathsheba Aug 22 '17 at 16:02
  • 2
    Note: this date only exists retrospectively. At the time, the year was different as it wasn't based on Jesus. March 25th was new year day, with March being the first month (btw Sept = 7, Oct = 8, Dec = 10) – Peter Lawrey Aug 22 '17 at 16:16
  • 2
    @PeterLawrey: Indeed. The term *proleptic* is used to describe the extrapolation of the Gregorian calendar backwards, including all its leap year shenanigans. Interestingly it's why the UK tax year starts on April 6th. Nice of you to remind us of the etymology of Sept, Oct, Nov, and Dec! – Bathsheba Aug 22 '17 at 16:22
  • 2
    @Bathsheba An obscure one for you; christian religious festivals which occur between Feb 25th and 28th are one day later in a leap year. i.e. the day added is Feb 25th, not Feb 29th, tracing back to the 25th being the first day of the year. – Peter Lawrey Aug 22 '17 at 16:28
  • 1
    @PeterLawrey As an organist I should have known that, but didn't! – Bathsheba Aug 22 '17 at 16:45
  • 1
    @Bathsheba correction it's Feb 24th not 25th ;) https://www.comedy.co.uk/tv/qi/episodes/12/13/ – Peter Lawrey Aug 22 '17 at 17:23
  • could someone give me a working example, as i'm not able to reproduce it with a calendar->date conversion falling to the 1st. I always get the 3rd, no matter if i use MIN_VALUE, MAX_VALUE or the real 0001-01-01 as GregorianChange Date. – John Doe Aug 23 '17 at 08:40

1 Answers1

6

Cute isn't it? The Java GregorianCalendar is not a proleptic Gregorian Calendar (despite its misleading name) but a composite calendar consisting of a Julian beginning and Gregorian end. (You can even set the cutover date yourself.)

In the Gregorian Calendar, January 1, 0001 is a Monday.

In the Julian Calendar, January 1, 0001 is a Saturday.

And there, my friends, is the difference of two days.

References:

https://www.timeanddate.com/calendar/?year=1&country=22 https://www.timeanddate.com/calendar/?year=1&country=23 https://en.wikipedia.org/wiki/Adoption_of_the_Gregorian_calendar https://docs.oracle.com/javase/7/docs/api/java/util/GregorianCalendar.html

See SetGregorianChange in the final link in particular.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483