4

在解析具有冲突区域 ID 和偏移量的字符串时,我找不到预期的行为。

例如:

ZonedDateTime d = ZonedDateTime.parse("2015-06-17T12:55:33+05:00[Europe/Amsterdam]");
println(d.toString()); // prints 2015-06-17T12:55:33+02:00[Europe/Amsterdam]

在这种情况下parse()似乎忽略了不正确的偏移量,+05:00并使用由区域 ID ( Europe/Amsterdam)确定的偏移量

正如文档所说:

偏移量不能自由设置,因为区域控制哪些偏移量是有效的。

我本来希望parse()抛出异常,因为+05:00zone 的偏移量无效Europe/Amsterdam。在这种情况下,正确的行为是什么?

4

1 回答 1

4

解析隐式调用 的静态from(TemporalAccessor)方法ZonedDateTime。它的文档说:

转换将首先从时间对象中获取 ZoneId,如有必要,将回退到 ZoneOffset。

这支持了与偏移信息相比,zone-id 是首选的观察结果。如果您明确使用严格模式,那么我会像您一样期待一个例外:

DateTimeFormatter dtf = 
  new DateTimeFormatterBuilder()
  .parseStrict()
  .appendPattern("uuuu-MM-dd'T'HH:mm:ssXXX'['VV']'").toFormatter();
ZonedDateTime d = ZonedDateTime.parse("2015-06-17T12:55:33+05:00[Europe/Amsterdam]", dtf);
System.out.println(d.toString()); // 2015-06-17T12:55:33+02:00[Europe/Amsterdam]

然而,没有观察到异常。并且parse(String)- 方法被记录为使用ISO_ZONED_DATE_TIME(我也测试了相同的结果),它也被定义为严格的。也许您可以向 Oracle 提出问题。由他们决定他们认为什么是“正确的行为”,即他们是否将此行为视为未记录的功能或错误。

我个人认为它是错误,因为例如表达式LocalDate.parse("Friday, 2016-03-08", new DateTimeFormatterBuilder().parseLenient().appendPattern("EEEE, uuuu-MM-dd").toFormatter().withLocale(Locale.ENGLISH))确实会由于矛盾的(工作日)信息而产生异常 - 即使在宽松模式下(这也不太好)。


作为对比:在我的时间库Time4J中,我实现了这样一个检查偏移信息是否一致。

ChronoFormatter<Moment> cf = 
    ChronoFormatter.ofMomentPattern("uuuu-MM-dd'T'HH:mm:ssXXX'['VV']'", PatternType.CLDR, Locale.ROOT, ZonalOffset.UTC);
System.out.println(cf.with(Leniency.STRICT).parse("2015-06-17T12:55:33+05:00[Europe/Amsterdam]"));
// Exception in thread "main" java.text.ParseException: Ambivalent offset information: AMSTERDAM versus +05:00

// this alternative formatter can be used as workaround for strict parsing
ZonedDateTime zdt = 
  ZonalDateTime.parse(
    "2015-06-17T12:55:33+05:00[Europe/Amsterdam]", 
    cf.with(Leniency.STRICT)
  ).toTemporalAccessor();
于 2016-03-08T13:12:00.040 回答