解析具有冲突区域 ID 和偏移量的字符串时 ZonedDateTime 的行为
behavior of ZonedDateTime when parsing string with conflicting zone id and offset
在解析具有冲突区域 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
)
确定的偏移量
正如 documentation 所说:
The offset cannot be freely set, as the zone controls which offsets are valid.
我预计 parse()
会抛出异常,因为 +05:00
是区域 Europe/Amsterdam
的无效偏移量。
在这种情况下,正确的行为是什么?
解析隐式调用 ZonedDateTime
的静态 from(TemporalAccessor)
方法。它的 documentation 说:
The conversion will first obtain a ZoneId from the temporal object,
falling back to a ZoneOffset if necessary.
这支持了与偏移量信息相比,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 提出问题。由他们决定他们将什么视为 "correct behaviour",即他们将此行为视为未记录的功能还是错误。
我个人认为这是一个错误,因为例如表达式 LocalDate.parse("Friday, 2016-03-08", new DateTimeFormatterBuilder().parseLenient().appendPattern("EEEE, uuuu-MM-dd").toFormatter().withLocale(Locale.ENGLISH))
确实会由于矛盾的(工作日)信息而产生异常 - 即使在宽松模式下(这也不太好)。
对比一下:在我的时间库Time4J中,实现了这样的检查offset信息是否一致。
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();
在解析具有冲突区域 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
)
正如 documentation 所说:
The offset cannot be freely set, as the zone controls which offsets are valid.
我预计 parse()
会抛出异常,因为 +05:00
是区域 Europe/Amsterdam
的无效偏移量。
在这种情况下,正确的行为是什么?
解析隐式调用 ZonedDateTime
的静态 from(TemporalAccessor)
方法。它的 documentation 说:
The conversion will first obtain a ZoneId from the temporal object, falling back to a ZoneOffset if necessary.
这支持了与偏移量信息相比,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 提出问题。由他们决定他们将什么视为 "correct behaviour",即他们将此行为视为未记录的功能还是错误。
我个人认为这是一个错误,因为例如表达式 LocalDate.parse("Friday, 2016-03-08", new DateTimeFormatterBuilder().parseLenient().appendPattern("EEEE, uuuu-MM-dd").toFormatter().withLocale(Locale.ENGLISH))
确实会由于矛盾的(工作日)信息而产生异常 - 即使在宽松模式下(这也不太好)。
对比一下:在我的时间库Time4J中,实现了这样的检查offset信息是否一致。
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();