Расхождение при преобразовании древних дат между java.util.Date и java.time.Instant - PullRequest
0 голосов
/ 18 сентября 2018

У меня есть устаревший код, который использует java.util.Date для создания древней даты (30 ноября 0002).Я пытаюсь обновить, какой код я могу, но для этого нужно конвертировать Date и LocalDate и т. Д. Я не могу полностью избавиться от использования Date или выбора древней даты.

Я нахожучто является ошибкой при переходе назад и вперед между датой и мгновением с этой древней датой, и надеялся, что кто-нибудь сможет объяснить, что происходит.

Вот пример:

    Date date = new Date();
    Instant instant = date.toInstant();
    System.out.println("Current:");
    System.out.println("Date: "+date);
    System.out.println("Instant: "+instant);
    System.out.println("Date epoch:    "+date.getTime());
    System.out.println("Instant epoch: "+instant.getEpochSecond()*1000);

    System.out.println("\nAncient from Date:");
    Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("MST"));
    cal.set(2, Calendar.NOVEMBER, 30, 0, 0, 0);
    date = cal.getTime();
    instant = date.toInstant();
    System.out.println("Date: "+date);
    System.out.println("Instant: "+instant);
    System.out.println("Date epoch:    "+date.getTime());
    System.out.println("Instant epoch: "+instant.getEpochSecond()*1000);

    System.out.println("\nAncient from Instant:");
    instant = Instant.parse("0002-11-30T00:00:00Z");
    date = Date.from(instant);
    System.out.println("Date: "+date);
    System.out.println("Instant: "+instant);
    System.out.println("Date epoch:    "+date.getTime());
    System.out.println("Instant epoch: "+instant.getEpochSecond()*1000);

Который печатает следующее:

Current:
Date: Tue Sep 18 12:34:27 MST 2018
Instant: 2018-09-18T19:34:27.177Z
Date epoch:    1537299267177
Instant epoch: 1537299267000

Ancient from Date:
Date: Thu Nov 30 00:00:00 MST 2
Instant: 0002-11-28T07:00:00.247Z
Date epoch:    -62075437199753
Instant epoch: -62075437200000

Ancient from Instant:
Date: Fri Dec 01 17:00:00 MST 2
Instant: 0002-11-30T00:00:00Z
Date epoch:    -62075289600000
Instant epoch: -62075289600000

Так что, если я создаю Мгновенное действие 30 ноября 2, а затем преобразую в Дату, Дата будет 1 декабря 2. Если я начну с Даты 30 ноября 2,Мгновенное время - 28 ноября. Я знаю, что ни Дата, ни Мгновенный не хранят информацию о часовом поясе, но почему эпохи так отличаются в зависимости от того, начал ли я с Даты против Мгновенного?Могу ли я в любом случае обойти это?Мне нужно начинать с даты или с момента и заканчивать тем же значением эпохи.Также было бы неплохо узнать, почему по умолчанию toString () показывает такие разные даты при одинаковой эпохе.

1 Ответ

0 голосов
/ 19 сентября 2018

Расхождение заключается в том, как реализации Date и Instant взаимодействуют друг с другом в связи с их реализациями, причем Date использует григорианские / юлианские календари, а Instant использует стандарт ISO для Date, которые следуют за модифицированным григорианским календарем ранее.к юлианскому календарному переключению.

В реализации GregorianCalendar есть специальное примечание:

Перед григорианским переключением GregorianCalendar реализует юлианский календарь.Единственная разница между григорианским и юлианским календарями - это правило високосного года.Юлианский календарь определяет високосные годы каждые четыре года, тогда как в григорианском календаре пропускаются столетние годы, которые не делятся на 400.

Ну, технически говоря, да.Но для этой проблемы мы не можем вполне столкнуться с этим.

cal.set(1582, Calendar.OCTOBER, 4, 0, 0, 0);

Это дает дату, как и ожидалось, 4 октября 1582 года.

cal.set(1582, Calendar.OCTOBER, 5, 0, 0, 0);

Это дает дату, октябрь 15 , 1582.

ЧТО ЭТО МАГИЯ, БАТМАН?

Ну, это не ошибка кодирования, это на самом делереализация GregorianCalendar.

Однако в этом году началось переключение григорианского календаря, когда папский бык, известный как «Интер грависим», ввел григорианский календарь, принятый Испанией, Португалией, Речью Посполитой.и большая часть современной Италии с самого начала.В этих странах год продолжался как обычно до четверга, 4 октября. Однако следующим днем ​​стала пятница, 15 октября (как обычный год, начинающийся в пятницу),

Из Википедии по 1582

Когда мы рассмотрим 4 октября 1582 г., происходит следующее:

Дата: 1582-окт-04 00: 00: 00

Мгновенный: 1582-10-14T00: 00: 00Z

Здесь 10-дневный разрыв, и причина, по которой момент существует в «технически несуществующую дату», заключается в том, чтоучитывается по определению мгновенных дат ISO .

Стандарт гласит, что каждая дата должна быть последовательной , поэтому использование юлианского календаря будет противоположнымк стандарту (потому что на дату переключения даты не будут последовательными).

ТАК, тогда как 14 октября 1582 года никогда не существовало в действительности, оно существует во времени ISO по определению, но происходит в реальном мире 4 октября 1582 года согласно юлианскому календарю.

Из-за того, что я предполагаю, есть дополнительные смещения високосного года из первого абзаца, где юлианские века 1500, 1400, 1300, 1100, 1000, 900, 700, 600, 500, 300, 200, 100 имеют дополнительные високосные дни, не учитываемые вПо григорианскому календарю мы медленно сдвигаемся назад от +10 к смещению -1.Это можно проверить, отрегулировав год с шагом +100.

Если вы отображаете даты исторических событий, вам лучше использовать Date или JulianCalendar DateFormatter для отображенияправильная правильная историческая дата, как это произошло в историиРаспечатка времени ISO для исторических периодов может показаться бессмысленной или неточной, но сохранение времени в этом формате все еще допустимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...