Joda: org.joda.time.IllegalInstantException: Незаконный момент из-за сдвига смещения часового пояса (переход на летнее время "пробел")

92
9

На Android-устройстве (7.0) произошел сбой:

Fatal Exception: org.joda.time.IllegalInstantException: Illegal instant due to time zone offset transition (daylight savings time 'gap'): 1977-05-01T00:00:00.000 (Africa/Casablanca)
at org.joda.time.chrono.ZonedChronology.localToUTC(ZonedChronology.java:157)
at org.joda.time.chrono.ZonedChronology.getDateTimeMillis(ZonedChronology.java:122)
at org.joda.time.chrono.AssembledChronology.getDateTimeMillis(AssembledChronology.java:133)
at org.joda.time.base.BaseDateTime.<init>(BaseDateTime.java:257)
at org.joda.time.base.BaseDateTime.<init>(BaseDateTime.java:198)
at org.joda.time.DateTime.<init>(DateTime.java:323)

Он появляется, когда часовой пояс: Африка/Касабланка (= GMT 0)

Мой код:

// Failed:
DateTime dateTime = new DateTime(year, month, 1);

// Failed
DateTime dateTime = new DateTime(year, month, 1, 0, 0, 0, 0,
DateTimeZone.forID(TimeZone.getDefault().getID()));

// Failed
DateTime dateTime = new DateTime(year, month, 1, 0, 0, 0,
DateTimeZone.forTimeZone(TimeZone.getDefault()));

Я не могу понять, почему это не удалось с этим часовым поясом. Если я использую другой часовой пояс (например, GMT + 1), проблем нет.

спросил(а) 2021-01-19T16:34:49+03:00 9 месяцев, 1 неделя назад
1
Решение
79

Это потому, что в мае 1-го 1977 года Касабланка перешел на летнее время: https://www.timeanddate.com/time/zone/morocco/casablanca?year=1977

В полночь часы были установлены на 1 час вперед до 1 часа ночи. Ему нравится "прыгать" с 11:59:59 до 1 часа ночи, поэтому в этот час в полночь не существует такой часовой пояс. Это называется разрыв (или разрыв в DST, если вы предпочитаете).

Joda-Time интерпретирует это как недопустимое значение в часовом поясе, над которым вы работаете, и, следовательно, исключение.

Если вы не хотите исключение, вы можете сначала проверить, если локальная дата и время действительны в этот часовой пояс:

LocalDateTime ld = new LocalDateTime(1977, 5, 1, 0, 0, 0, 0);
DateTimeZone zone = DateTimeZone.forID("Africa/Casablanca");
System.out.println(zone.isLocalDateTimeGap(ld)); // true

// if it not a gap (isLocalDateTimeGap is false), it safe to create DateTime
DateTime d = ld.toDateTime(zone);

В этом случае он печатает true, потому что 1 мая 1977 года в полночь будет разрыв в часовом поясе в Касабланке, поэтому создание DateTime для этих значений вызовет исключение.

Это не происходит в других часовых поясах, потому что они имеют разные правила DST, а дата и время действительны для них.

ответил(а) 2021-01-19T16:34:49+03:00 9 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема