Преобразование календаря в дату для дат до 15 октября 1582 г. Переключение григорианского в юлианский календарь

Учитывая, что дата начала григорианского календаря - 15 октября 1582 года, рассмотрите следующие тесты и помогите мне понять, что происходит:

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("\nnew 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("\nnew 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("\nnew 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("\nString to parse: " + dateToParse);
    calendar = parseDateTime(dateToParse);
    if(calendar != null) {
        date = calendar.getTime();
        System.out.println("datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() -> \n    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("\nString to parse: " + dateToParse);
    calendar = parseDateTime(dateToParse);
    if(calendar != null) {
        date = calendar.getTime();
        System.out.println("datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() -> \n    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("\nString to parse: " + dateToParse);
    calendar = parseDateTime(dateToParse);
    if(calendar != null) {
        date = calendar.getTime();
        System.out.println("datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() -> \n    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("\nString to parse: " + dateToParse);
    calendar = parseDateTime(dateToParse);
    if(calendar != null) {
        date = calendar.getTime();
        System.out.println("datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() -> \n    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;
}

Результаты следующие:

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**

Не могли бы вы разъяснить мне, что происходит? Большое спасибо.

РЕДАКТИРОВАТЬ: Спасибо, я исправил свои ошибки в формате даты для анализа: теперь все имеют форму yyyy-MM-gg, и больше не выдается никаких исключений.

Сейчас я пытаюсь уточнить мои сомнения.

От чего зависит, будем ли мы использовать пролегический григорианский календарь?
Подводя итог:
java.util.GregorianCalendar представляет собой юлианский календарь для дат до 15 октября 1582 года и григорианский календарь после этой даты. Это правильно?
Итак, это оправдывает поведение в новом GregorianCalendar (...) ...
Если я сделаю:

new GregorianCalendar(1582, 9, 4) 

у меня есть

calendar[DAY_OF_MONTH [4], MONTH [9], YEAR [1582]]  

потому что 4 октября 1582 года существует в юлианском календаре, а созданный мной календарь представляет юлианскую дату.
Преобразовав этот календарь в дату, мы имеем:

Date:Thu Oct 04 00:00:00 CET 1582, consistent with Calendar.  

Если я сделаю:

new GregorianCalendar(1582, 9, 5)   

Я получаю

calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]]  

потому что 5 октября не существует ни в юлианском, ни в григорианском календаре. Таким образом, конструктор GregorianCalendar создает дату ровно через 1 день после 4 октября, то есть первого дня григорианского календаря, 15 октября. Новая дата затем выражается в системе григорианского календаря.
У меня будет такое же поведение при создании нового календаря с датами (1582, 9, 5) и (1582, 9, 14).
В приведенном выше примере преобразованная java.util.Date снова соответствует календарю.

Date:Fri Oct 15 00:00:00 CET 1582  

Если я сделаю:

new GregorianCalendar(1582, 9, 15)  

у меня есть

calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]]  

потому что 15 октября существует в григорианском календаре и новая дата выражается в этой системе. Календарь, преобразованный в дату, снова соответствует:

Date:Fri Oct 15 00:00:00 CET 1582  

Это означает, что конструктор GregorianCalendar предполагает, что я ввожу даты в календарную систему, которая действительна в данную эпоху: другими словами, предполагается, что если я введу дату, предшествующую или равную 04 октября, я думаю, что дата соответствует юлианскому календарь и дата выражается в этой системе, если я ввожу дату между 05 и 14 октября, она подсчитывает количество дней между датой окончания юлианского календаря (04 октября) и датой, которую я ввела, и суммирует эти дни с датой начала григорианского календаря (15 октября) и выражают новую дату в григорианской системе, и если я ввожу дату после или равную 15 октября, это предполагает, что введенная мной дата подразумевается в григорианском календаре, и новая дата выражается в этой системе.
Все ли это правильно?
Это не пролетическое поведение, верно? Если бы календарь был григорианским календарем, я бы ожидал, что его инициализация

new GregorianCalendar(1582, 9, 5)  

Я бы получил

calendar[DAY_OF_MONTH [5], MONTH [9], YEAR [1582]]  

то есть 5 октября устанавливается также, если дата не существует в григорианской системе и, будучи 10 днями до первого дня григорианского календаря, она будет равна юлианской дате 25 сентября, если я не ошибаюсь.
Как я могу решить, использовать ли мне григорианский календарь и нет?

Синтаксический анализ строки и создание нового GregorianCalendar, проходящего через XmlGregorianCalendar, поведение мне кажется другим.
Разбор "1582-10-04" получаю

calendar[DAY_OF_MONTH [4], MONTH [9], YEAR [1582]] 

(так же, как в примере выше ..), но дата

Date: Mon Sep 24 00:00:00 CET 1582 

(Здесь у нас есть юлианская дата, верно? Но в приведенном выше примере (где GregorianCalendar был создан его конструктором) Дата была равна Календарю. Почему теперь она другая?

Разбор строки "1582-10-05" у нас

calendar[DAY_OF_MONTH [5], MONTH [9], YEAR [1582]] 

(Теперь у нас есть Григорианский календарь Proleptic, верно?)
Но опять другая дата

Date: Tue Sep 25 00:00:00 CET 1582 (Julian Date? Why?)  

Такое же поведение при разборе "1582-10-14"

calendar[DAY_OF_MONTH [14], MONTH [9], YEAR [1582]]  
Date: Thu Oct 04 00:00:00 CET 1582  

Если мы наконец разберем «1582-10-15», мы вернемся к григорианскому веку, и все станет последовательным:

calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]]  
Date: Fri Oct 15 00:00:00 CET 1582  

Можете ли вы помочь мне понять все это поведение?
Большое спасибо.

РЕДАКТИРОВАТЬ 2:

Спасибо за ваши ответы, а также, если у меня останутся сомнения. Я попробовал следующий код:

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 ["+prolepticDate+"]");

Выход был:

proleptic [DAY_OF_MONTH [5], MONTH [9], YEAR [1582]
prolepticDate [Tue Sep 25 00:24:07 CET 1582]

Теперь у меня есть календарь с DAY_OF_MONTH в соответствии с тем, что я установил, так что я думаю, что это пролетическое поведение, верно? Но снова я спрашиваю, почему Date, полученный методом getTime (), не представляет тот же день, но 10 дней назад. Еще раз спасибо.

РЕДАКТИРОВАТЬ 3:

Вопрос для меня немного понятнее, но не полностью. Я не понял подробно, по какой логике выполняется преобразование из GregorianCalendar в Date и почему логический григорианский календарь и традиционный, каждый из которых построен с такими же параметрами, как DAY, MONTH и YEAR, не всегда представляют один и тот же момент времени. Я сделал несколько дальнейших тестов.

GregorianCalendar proleptic = null;
GregorianCalendar calendar = null;
Date date = null;

// ---- JULIAN PERIOD ----
proleptic = new GregorianCalendar();
proleptic.clear(); 
proleptic.setGregorianChange(new Date(Long.MIN_VALUE));
proleptic.set(Calendar.DAY_OF_MONTH, 5);
proleptic.set(Calendar.MONTH, Calendar.FEBRUARY);
proleptic.set(Calendar.YEAR, 1582);
System.out.println("proleptic_calendar_5Feb1582 [DAY_OF_MONTH ["+proleptic.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+proleptic.get(Calendar.MONTH)+"], YEAR ["+proleptic.get(Calendar.YEAR)+"]");
date = proleptic.getTime();
System.out.println("date_5Feb1582 from proleptic ["+date+"]");

calendar = new GregorianCalendar(1582, 1, 5);
date = calendar.getTime();
System.out.println("new GregorianCalendar(1582, 1, 5)            -> [DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("new GregorianCalendar(1582, 1, 5) .getTime() -> Date:" + date);

System.out.println("proleptic_calendar_5Feb1582 in millis ["+proleptic.getTimeInMillis()+"], new GregorianCalendar(1582, 1, 5) in millis ["+calendar.getTimeInMillis()+"], millis are equal ["+ (proleptic.getTimeInMillis() == calendar.getTimeInMillis()) +"]");
//--------

System.out.println("\n");

// ---- transition period ----
proleptic = new GregorianCalendar();
proleptic.clear(); 
proleptic.setGregorianChange(new Date(Long.MIN_VALUE));
proleptic.set(Calendar.DAY_OF_MONTH, 8);
proleptic.set(Calendar.MONTH, Calendar.OCTOBER);
proleptic.set(Calendar.YEAR, 1582);
System.out.println("proleptic_calendar_8Oct1582 [DAY_OF_MONTH ["+proleptic.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+proleptic.get(Calendar.MONTH)+"], YEAR ["+proleptic.get(Calendar.YEAR)+"]");
date = proleptic.getTime();
System.out.println("date_5Oct1582 from proleptic ["+date+"]");

calendar = new GregorianCalendar(1582, 9, 8);
date = calendar.getTime();
System.out.println("new GregorianCalendar(1582, 9, 8)            -> [DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("new GregorianCalendar(1582, 9, 8) .getTime() -> Date:" + date);

System.out.println("proleptic_calendar_8Oct1582 in millis ["+proleptic.getTimeInMillis()+"], new GregorianCalendar(1582, 9, 8) in millis ["+calendar.getTimeInMillis()+"], millis are equal ["+ (proleptic.getTimeInMillis() == calendar.getTimeInMillis()) +"]");
//--------

System.out.println("\n");

// ---- GREGORIAN PERIOD ----
proleptic = new GregorianCalendar();
proleptic.clear(); 
proleptic.setGregorianChange(new Date(Long.MIN_VALUE));
proleptic.set(Calendar.DAY_OF_MONTH, 5);
proleptic.set(Calendar.MONTH, Calendar.DECEMBER);
proleptic.set(Calendar.YEAR, 1582);
System.out.println("proleptic_calendar_5Dec1582 [DAY_OF_MONTH ["+proleptic.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+proleptic.get(Calendar.MONTH)+"], YEAR ["+proleptic.get(Calendar.YEAR)+"]");
date = proleptic.getTime();
System.out.println("date_5Dec1582 from proleptic ["+date+"]");

calendar = new GregorianCalendar(1582, 11, 5);
date = calendar.getTime();
System.out.println("new GregorianCalendar(1582, 11, 5)            -> [DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("new GregorianCalendar(1582, 11, 5) .getTime() -> Date:" + date);

System.out.println("proleptic_calendar_5Dec1582 in millis ["+proleptic.getTimeInMillis()+"], new GregorianCalendar(1582, 11, 5) in millis ["+calendar.getTimeInMillis()+"], millis are equal ["+ (proleptic.getTimeInMillis() == calendar.getTimeInMillis()) +"]");
//--------

Выход был:

proleptic_calendar_5Feb1582 [DAY_OF_MONTH [5], MONTH [1], YEAR [1582]
date_5Feb1582 from proleptic [Fri Jan 26 00:00:00 CET 1582]
new GregorianCalendar(1582, 1, 5)            -> [DAY_OF_MONTH [5], MONTH [1], YEAR [1582]]
new GregorianCalendar(1582, 1, 5) .getTime() -> Date:Mon Feb 05 00:00:00 CET 1582
proleptic_calendar_5Feb1582 in millis [-12241069200000], new GregorianCalendar(1582, 1, 5) in millis [-12240205200000], millis are equal [false]

proleptic_calendar_8Oct1582 [DAY_OF_MONTH [8], MONTH [9], YEAR [1582]
date_5Oct1582 from proleptic [Fri Sep 28 00:00:00 CET 1582]
new GregorianCalendar(1582, 9, 8)            -> [DAY_OF_MONTH [18], MONTH [9], YEAR [1582]]
new GregorianCalendar(1582, 9, 8) .getTime() -> Date:Mon Oct 18 00:00:00 CET 1582
proleptic_calendar_8Oct1582 in millis [-12219901200000], new GregorianCalendar(1582, 9, 8) in millis [-12219037200000], millis are equal [false]

proleptic_calendar_5Dec1582 [DAY_OF_MONTH [5], MONTH [11], YEAR [1582]
date_5Dec1582 from proleptic [Sun Dec 05 00:00:00 CET 1582]
new GregorianCalendar(1582, 11, 5)            -> [DAY_OF_MONTH [5], MONTH [11], YEAR [1582]]
new GregorianCalendar(1582, 11, 5) .getTime() -> Date:Sun Dec 05 00:00:00 CET 1582
proleptic_calendar_5Dec1582 in millis [-12214890000000], new GregorianCalendar(1582, 11, 5) in millis [-12214890000000], millis are equal [true]

Первый тест (5 февраля 1582 г.) относится к периоду, относящемуся к юлианскому календарю, второй (8 октября 1582 г.) относится к периоду перехода, третий (5 декабря 1582 г.) к периоду григорианского календаря. Тогда я думаю отметить следующие вещи:

Юлианский период

Григорианский календарь с пролеплением, кажется, представляет желаемую датуПолученная дата, как объясняет @Meno Hochschild, конвертируется в юлианскую дату (-10 дней)традиционный григорианский календарь также, кажется, представляет желаемую дату ...но полученная дата отличается от предыдущейна самом деле, два григорианских календаря представляют два разных момента времени, см. значения в миллисекундах

переходный период

Григорианский календарь с пролеплением, кажется, представляет желаемую датуПолученная дата снова конвертируется в юлианскую дату (-10 дней)традиционный григорианский календарь, по-видимому, является результатом преобразования в григорианском календаре даты (8 октября), первоначально выраженной в пролептическом юлианском календаре (8 октября = на 4 дня больше, чем в юлианском календаре. Макс. дата (4 октября) = на 3 дня больше, чем Григорианский календарь минимальная дата = 15 + 3 = 18 октября (это предположение)на этот раз полученная дата, по-видимому, представляет собой ту же дату из указанного выше традиционного григорианского календаря (на этот раз без преобразования в юлианскую дату?)два григорианских календаря снова представляют два разных момента времени, см. значения в миллисекундах

Григорианский период

Григорианский календарь пролептика представляет желаемую датуПолученная дата представляет собой ту же датутрадиционный григорианский календарь представляет желаемую датуПолученная дата представляет собой ту же датудва григорианских календаря представляют одно и то же время, одинаковое количество миллисекунд

Не могли бы вы помочь мне объяснить один за другим все эти результаты?

Благодарю.

Ответы на вопрос(1)

Ваш ответ на вопрос