Joda:org.joda.time.IllegalInstantException:由于时区偏移过渡而导致的非法瞬间(夏令时'间隙')

时间:2018-02-08 07:58:26

标签: java android datetime timezone jodatime

在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)

当时区出现时:Africa / Casablanca(= 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),则完全没有问题。

1 个答案:

答案 0 :(得分:2)

那是因为1977年5月1日,卡萨布兰卡改为夏令时:https://www.timeanddate.com/time/zone/morocco/casablanca?year=1977

午夜,时钟设定为1小时前至凌晨1点。它就像它跳了#34;从晚上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's not a gap (isLocalDateTimeGap is false), it's safe to create DateTime
DateTime d = ld.toDateTime(zone);

在这种情况下,它打印true,因为1977年5月1日午夜是卡萨布兰卡时区的一个空白,因此为这些值创建DateTime会引发异常。

它不会发生在其他时区,因为它们有不同的DST规则,日期和时间对它们有效。