如何处理由于时区偏移转换而导致的 jodatime 非法即时

2022-09-01 00:35:57

我想将joda设置为今天凌晨2点(请参阅下面的示例代码)。但是我得到了这个例外:DateTime

Exception in thread "main" org.joda.time.IllegalFieldValueException: Value 2 for hourOfDay is not supported: Illegal instant due to time zone offset transition: 2011-03-27T02:52:05.239 (Europe/Prague)
at org.joda.time.chrono.ZonedChronology$ZonedDateTimeField.set(ZonedChronology.java:469)
at org.joda.time.MutableDateTime.setHourOfDay(MutableDateTime.java:702)

处理上述异常或在一天中的特定时间创建 异常 的正确方法是什么?DateTime

示例代码:

MutableDateTime now = new MutableDateTime();
now.setHourOfDay(2);
now.setMinuteOfHour(0);
now.setSecondOfMinute(0);
now.setMillisOfSecond(0);
DateTime myDate = now.toDateTime();

谢谢。


答案 1

您似乎正在尝试从特定的本地时间获取到实例,并且希望它对夏令时具有鲁棒性。试试这个...(注意我在美国/东部,所以我们的过渡日期是13 Mar 11;我必须找到合适的日期才能得到你今天得到的例外。更新了我下面的CET代码,今天转换。这里的见解是,Joda提供LocalDateTime,让您了解本地挂钟设置以及它在您所在时区是否合法。在本例中,如果时间不存在,我只需添加一个小时(您的应用程序必须确定这是否是正确的策略)。DateTime

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;

class TestTz {

  public static void main(String[] args)
  {
     final DateTimeZone dtz = DateTimeZone.forID("CET");
     LocalDateTime ldt = new LocalDateTime(dtz)
       .withYear(2011)
       .withMonthOfYear(3)
       .withDayOfMonth(27)
       .withHourOfDay(2);

    // this is just here to illustrate I'm solving the problem; 
    // don't need in operational code
    try {
      DateTime myDateBorken = ldt.toDateTime(dtz);
    } catch (IllegalArgumentException iae) {
      System.out.println("Sure enough, invalid instant due to time zone offset transition!");
    }

    if (dtz.isLocalDateTimeGap(ldt)) {
      ldt = ldt.withHourOfDay(3);
    }

    DateTime myDate = ldt.toDateTime(dtz);
    System.out.println("No problem: "+myDate);
  }

}

此代码生成:

Sure enough, invalid instant due to time zone offset transition!
No problem: 2011-03-27T03:00:00.000+02:00

答案 2

CET 在 3 月的最后一个星期日切换到 DST(夏令时),恰好是今天。时间从 1:59:59 到 3:00:00 – 没有 2,因此例外。

您应该使用 UTC 而不是本地时间,以避免此类时区问题。

MutableDateTime now = new MutableDateTime(DateTimeZone.UTC);

推荐