Преобразование LocalDateTime года 2CE на один день при преобразовании в java.util.Date

У меня есть дата, представленная строкой «0002-01-04T00:49:40.000», то есть дата в году 2CE. Мне нужно преобразовать его в экземпляр java.util.Date, объединив его с идентификатором часового пояса «Etc/UTC». Следующий код показывает, как я это делаю:

public static Date toDate(LocalDateTime localDateTime, String timezoneId){
    if(localDateTime == null) return null;
    if(timezoneId != null) {
        localDateTime.toDateTime(DateTimeZone.forID(timezoneId)).toDate();
    } else {
        return localDateTime.toDateTime().toDate()
    }
}

Но LocalDateTime.toDate() работает неправильно. Это добавляет +1 день к дате.

"0002-01-04T00:49:40.000Z" ---> "Чт, 5 января, 16:49:40 PST 2".


person Flame023    schedule 29.11.2016    source источник
comment
Возможный дубликат Как преобразовать строку даты и времени в дату, используя GWT?   -  person DimaSan    schedule 30.11.2016
comment
toDate() — это метод JodaTime.   -  person DimaSan    schedule 30.11.2016
comment
java.util.Date.toString() использует юлианский календарь для 0002 года! Так что я не вижу ни проблемы, ни провала.   -  person Meno Hochschild    schedule 30.11.2016
comment
@DimaSan Ссылка, которую вы разместили, не решает конкретную проблему OP в отношении наблюдаемого вывода, см. Мой ответ.   -  person Meno Hochschild    schedule 30.11.2016


Ответы (1)


Как указано в моем комментарии, ошибки НЕТ. Все правильно, хотя вы не ожидали того результата, который вы наблюдали. Поэтому я объясню это подробно. Пример кода на основе вашего вспомогательного метода:

System.out.println(
    toDate(org.joda.time.LocalDateTime.parse("0002-01-04T00:49:40.000"), "GMT")
); // Fri Jan 06 01:49:40 CET 2

Вывод основан на методе java.util.Date.toString(). Что сбивает с толку в этом методе:

  • Используется системный часовой пояс (в моем случае GMT+01:00). Следовательно, эта деталь объясняет, почему в моем случае время опережает время на один час (а в вашем случае на 8 часов отстает от UTC из-за вашей зоны PST). Если рассматривать только время, то в качестве даты мы ожидаем тот же день для GMT+01 и на день раньше для PST...

  • Менее известный, но очень важный: вывод java.util.Date.toString() использует смешанный календарь с григорианским переходом, установленным на 1582-10-15. До этой даты используется юлианский календарь. И вы используете год 0002! Итак, здесь мы сравниваем пролепптическую дату по григорианскому календарю в Joda-Time с датой по юлианскому календарю. Для 0002 года разница между обоими календарями составляет два дня из-за разных правил високосного года. По юлианскому календарю в 0002 году на два дня больше. Как понять эти два дня? Годы 100, 200, 300, 500, 600, 700, 900, 1000, 1100, 1300, 1400 и 1500 не являются високосными годами в григорианском календаре, в то время как високосные годы в юлианском календаре => разница в 12 дней. Но папа Грегор вычеркнул 10 дней в 1582 году (следующий день после 1582-10-04 был 1582-10-15). Следовательно: 12 - 10 = дельта в 2 дня для лет до 100 г. н.э. и после 99 г. до н.э.

  • Подведение итогов: [0002-01-04] минус один день (коррекция времени по тихоокеанскому стандартному времени) плюс два дня (коррекция календаря) дает [0002-01-05] то, что вы наблюдаете.

person Meno Hochschild    schedule 30.11.2016