2016-03-08 21 views
3

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

例如:

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

作为documentation说:

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

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

回答

3

该解析隐含地调用静态from(TemporalAccessor)-方法ZonedDateTime。它documentation说:

转换将首先得到暂时物件, 回落到ZoneOffset如果有必要了zoneid。

这支持了观察,即与偏移信息相比,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提交问题。如果他们认为这种行为是无证的功能或错误,他们可以决定他们认为是“正确的行为”。

我个人认为它是bug,因为例如表达式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(); 
相关问题