Given that Gregorian Calendar start date is 15 Oct 1582, please consider the following tests and please help me understanding what happens:
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import org.junit.Test;
@Test
public void gregorianToDateConversion() {
GregorianCalendar calendar = null;
Date date = null;
calendar = new GregorianCalendar(1582, 9, 04);
date = calendar.getTime();
System.out.println("new GregorianCalendar(1582, 9, 4) -> calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date:" + date);
calendar = new GregorianCalendar(1582, 9, 05);
date = calendar.getTime();
System.out.println("
new GregorianCalendar(1582, 9, 5) -> calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date:" + date);
calendar = new GregorianCalendar(1582, 9, 14);
date = calendar.getTime();
System.out.println("
new GregorianCalendar(1582, 9, 14) -> calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date:" + date);
calendar = new GregorianCalendar(1582, 9, 15);
date = calendar.getTime();
System.out.println("
new GregorianCalendar(1582, 9, 15) -> calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date:" + date);
String dateToParse = null;
dateToParse = "1582-10-04";
System.out.println("
String to parse: " + dateToParse);
calendar = parseDateTime(dateToParse);
if(calendar != null) {
date = calendar.getTime();
System.out.println("datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date: " + date);
}
dateToParse = "1582-10-05";
System.out.println("
String to parse: " + dateToParse);
calendar = parseDateTime(dateToParse);
if(calendar != null) {
date = calendar.getTime();
System.out.println("datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date: " + date);
}
dateToParse = "1582-10-14";
System.out.println("
String to parse: " + dateToParse);
calendar = parseDateTime(dateToParse);
if(calendar != null) {
date = calendar.getTime();
System.out.println("datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date: " + date);
}
dateToParse = "1582-10-15";
System.out.println("
String to parse: " + dateToParse);
calendar = parseDateTime(dateToParse);
if(calendar != null) {
date = calendar.getTime();
System.out.println("datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date: " + date);
}
}
private GregorianCalendar parseDateTime(String s) {
DatatypeFactory datatypeFactory = null;
try {
datatypeFactory = DatatypeFactory.newInstance();
return datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
The results are the following:
new GregorianCalendar(1582, 9, 4) -> calendar[DAY_OF_MONTH [4], MONTH [9], YEAR [1582]] **OK**
calendar.getTime() -> Date:Thu Oct 04 00:00:00 CET 1582 **OK**
new GregorianCalendar(1582, 9, 5) -> calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]] **+ 10 days ??**
calendar.getTime() -> Date:Fri Oct 15 00:00:00 CET 1582 **coherent with calendar**
new GregorianCalendar(1582, 9, 14) -> calendar[DAY_OF_MONTH [24], MONTH [9], YEAR [1582]] **+ 10 days ??**
calendar.getTime() -> Date:Sun Oct 24 00:00:00 CET 1582 **coherent with calendar**
new GregorianCalendar(1582, 9, 15) -> calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]] **OK**
calendar.getTime() -> Date:Fri Oct 15 00:00:00 CET 1582 **OK**
String to parse: 1582-10-04
datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH [4], MONTH [9], YEAR [1582]]
calendar.getTime() -> Date: Mon Sep 24 00:00:00 CET 1582 **Not coherent with calendar. Conversion to julian date?**
String to parse: 1582-10-05
datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH [5], MONTH [9], YEAR [1582]]
calendar.getTime() -> Date: Tue Sep 25 00:00:00 CET 1582 **Not coherent with calendar. Conversion to julian date?**
String to parse: 1582-10-14
datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH [14], MONTH [9], YEAR [1582]] **OK**
calendar.getTime() -> Date: Thu Oct 04 00:00:00 CET 1582 **Not coherent with calendar. Conversion to julian date?**
String to parse: 1582-10-15
datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]] **OK**
calendar.getTime() -> Date: Fri Oct 15 00:00:00 CET 1582 **OK**
Could you clarify me what is happening?
Thank you very much.
EDIT:
Thank you, I've fixed my mistakes about the format of the date to parse: now all have the form yyyy-MM-gg and no exceptions are thrown anymore.
Now I try to clarify my dubts.
What determines whether or not we are using the proleptic gregorian calendar?
By summarizing:
java.util.GregorianCalendar represents a julian calendar for dates before 15 Oct 1582 and a gregorian calendar after this date. Is it right?
So, this justifies the behaviour in the new GregorianCalendar(...)...
If I do:
new GregorianCalendar(1582, 9, 4)
I have
calendar[DAY_OF_MONTH [4], MONTH [9], YEAR [1582]]
because 4 Oct 1582 exists in the julian calendar and the calendar I've created represents a julian date.
Converting this calendar to date, we have:
Date:Thu Oct 04 00:00:00 CET 1582, consistent with Calendar.
If I do:
new GregorianCalendar(1582, 9, 5)
I obtain
calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]]
because the day 5 of October neither exists in julian nor in gregorian calendar. So the GregorianCalendar constructor creates a date exactely 1 day after the 4 of October, that is the first day of the gregorian calendar, the 15 of October. The new date is then expressed in gregorian calendar system.
I'll have the same behaviour creating a new calendar passing dates from (1582, 9, 5) to (1582, 9, 14).
In the example above, the converted java.util.Date is again consistent with the Calendar
Date:Fri Oct 15 00:00:00 CET 1582
If I do:
new GregorianCalendar(1582, 9, 15)
I have
calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]]
because 15 of October exists in gregorian calendar and the new date is expressed in this system.
The Calendar converted into Date is again consistent:
Date:Fri Oct 15 00:00:00 CET 1582
This means that the GregorianCalendar constructor assumes that I enter dates in the calendar system that is valid in the given epoch: in other words assumes that if I enter a date prior then or equal to 04 October I'm thinking the date according to the julian calendar and the date is expressed in this system, if I enter a date between 05 and 14 October it counts the number of days between the end date of julian calendar (04 october) and the date I entered and sums this days to the start date of gregorian calendar (15 October) and express the new date in gregorian system, and if I enter a date after or equal to 15 October it assumes that the date I entered is meant in gregorian calendar and the new date is expressed in this system.
Is all this correct?
This is not a proleptic behaviour, right? If the calendar was a proleptic gregorian calendar I would expect that initializing it with
new GregorianCalendar(1582, 9, 5)
I would obtain
calendar[DAY_OF_MONTH [5], MONTH [9], YEAR [1582]]
that is the 5 of October is set also if the date does not exists in the gregorian system and, being 10 days befor the first day of gregorian calendar, it would be equal to the julian date 25 september, if I'm not mistaken.
How can I decide to use the proleptic gregorian calendar or not?
Parsing a String and creating a new GregorianCalendar passing through the XmlGregorianCalendar, the behaviour seems to me different.
Parsing "1582-10-04" I obtain
calendar[DAY_OF_MONTH [4], MONTH [9], YEAR [1582]]
(same as the example above..) but a date
Date: Mon Sep 24 00:00:00 CET 1582
(Here we have a julian date, is it right? But in the example above (where the GregorianCalendar was created by its constructor) the Date was equal to the Calendar. Why now it is different?
Parsing the string "1582-10-05" we have
calendar[DAY_OF_MONTH [5], MONTH [9], YEAR [1582]]
(Now we have a Proleptic gregorian calendar, right?)
But again a different Date
Date: Tue Sep 25 00:00:00 CET 1582 (Julian Date? Why?)
Same behaviour parsing "1582-10-14"
calendar[DAY_OF_MONTH [14], MONTH [9], YEAR [1582]]
Date: Thu Oct 04 00:00:00 CET 1582
If we finally parse "1582-10-15", we come back in the Gregorian age ad all become consistent:
calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]]
Date: Fri Oct 15 00:00:00 CET 1582
Can you help me to understand all this behaviours?
Thank you very much.
EDIT 2:
Thank you for your answers, also if some doubt remains for me.
I tried the following code:
GregorianCalendar proleptic = new GregorianCalendar();
proleptic.setGregorianChange(new Date(Long.MIN_VALUE));
proleptic.set(Calendar.DAY_OF_MONTH, 5);
proleptic.set(Calendar.MONTH, 9);
proleptic.set(Calendar.YEAR, 1582);
System.out.println("proleptic [DAY_OF_MONTH ["+proleptic.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+proleptic.get(Calendar.MONTH)+"], YEAR ["+proleptic.get(Calendar.YEAR)+"]");
Date prolepticDate = proleptic.getTime();
System.out.println("prolepticDate ["+prolepticD