由于时区偏移转换,如何处理jodatime非法即时

我想在今天凌晨2点设置joda 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) 

上面的句柄exception的正确方法是什么,或者在特定的时刻创buildDateTime

示例代码:

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

谢谢。

看起来你正试图从一个特定的本地时间到一个DateTime实例,并希望这是夏时制强大的。 试试这个…(注意我在美国/东部,所以我们的过渡date是11年3月13日,我必须find正确的date以得到你今天得到的例外。 )这里的洞察是,Joda提供了LocalDateTime ,让你理解一个本地挂钟设置,以及它是否在你的时区合法。 在这种情况下,如果时间不存在,我只需添加一小时(您的应用程序必须决定这是否是正确的策略)。

 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); } } 

这段代码产生:

果然,由于时区偏移转换造成的无效瞬间!
没问题:2011-03-27T03:00:00.000 + 02:00

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

您应该使用UTC而不是本地时间来避免这种时区问题。

 MutableDateTime now = new MutableDateTime(DateTimeZone.UTC); 

我想很多时候,你会想要乔达自动为你解决这个问题。 你通常不知道修正差距date的正确方法,因为差距的大小取决于区域和年份(尽pipe当然通常是一个小时)。

其中一个例子是,如果您正在parsing来自您不受控制的源的时间戳, 例如networking。 如果时间戳的发件人已经过时了区域文件,则可能发生这种情况。 (如果你有过时的区域文件,你几乎搞砸了)。

这是一个方法来做到这一点,这是,稍微复杂一点。 我已经在joda 1.6以及2.x中工作了,因为我们在我们的环境中恰好陷入了1.6。

如果您正在根据您的问题build立其他input的date,则可以按照上面的build议以UTCdate或LocalDate开始,然后调整它以自动修正偏移量。 特别酱在DateTimeZone.convertLocalToUTC

危险:

 public DateTime parse(String str) { formatter.parseDateTime(gapdate) } 

安全:

 public DateTime parse(String str) { // separate date from zone; you may need to adjust the pattern, // depending on what input formats you support String[] parts = str.split("(?=[-+])"); String datepart = parts[0]; DateTimeZone zone = (parts.length == 2) ? DateTimeZone.forID(parts[1]) : formatter.getZone(); // parsing in utc is safe, there are no gaps // parsing a LocalDate would also be appropriate, // but joda 1.6 doesn't support that DateTime utc = formatter.withZone(DateTimeZone.UTC).parseDateTime(datepart); // false means don't be strict, joda will nudge the result forward by the // size of the gap. The method is somewhat confusingly named, we're // actually going from UTC to local long millis = zone.convertLocalToUTC(utc.getMillis(), false); return new DateTime(millis, zone); } 

我已经在东半球和西半球以及豪勋爵岛地区进行了testing,这个地区恰好有半个小时的时间。

这将是一种很好,如果乔达格式化器将支持一个setStrict(布尔),让他们照顾你这个…

如果你需要从stringparsingdate:

 final DateTimeZone dtz = DateTimeZone.getDefault(); //DateTimeZone.forID("Europe/Warsaw") LocalDateTime ldt = new LocalDateTime("1946-04-14", dtz); if (dtz.isLocalDateTimeGap(ldt)){ ldt = ldt.plusHours(1); } DateTime date = ldt.toDateTime(); Date date = date.toDate(); 

为我完美工作。 也许有人会需要它。

更新到jodatime 2.1并使用LocalDate.parse()

 DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy"); LocalDate.parse(date, formatter);