解析日期时无法从TemporalAccessor获取ZonedDateTime

时间:2016-03-11 15:38:56

标签: java datetime java-8 java-time

使用Java 1.8.0_51以下代码(取自Unable to obtain OffsetDateTime from TemporalAccessor

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd").withZone(ZoneId.of("Europe/Berlin"));
OffsetDateTime offsetDateTime = ZonedDateTime.parse("20151113", formatter).toOffsetDateTime();
System.out.println(offsetDateTime.format(DateTimeFormatter.ISO_DATE));

抛出异常:

java.time.format.DateTimeParseException: Text '20151113' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {},ISO,Europe/Berlin resolved to 2015-11-13 of type java.time.format.Parsed
at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1918)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1853)
at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)

这次我做错了什么?

2 个答案:

答案 0 :(得分:5)

你忘了设定时间。

如果将my answer与您的代码进行比较,您会发现唯一的区别是缺少时间信息。 ZonedDateTime包含时间信息,由于您当前的格式化程序无法处理它,因此无法形成ZonedDateTime的实例。

您还可以在包含

的堆栈跟踪中看到它
Caused by: java.time.DateTimeException: Unable to obtain LocalTime from TemporalAccessor: {},ISO,Europe/Berlin resolved to 2015-11-13 of type java.time.format.Parsed
    at java.time.LocalTime.from(LocalTime.java:409)
    at java.time.ZonedDateTime.from(ZonedDateTime.java:560)
    ... 5 more

根据您的需要,您可以使用DateTimeFormatterBuilder构建自定义格式化程序,并调用parseDefaulting为每个时间字段字段提供默认值。如果您想默认为午夜,可以将NANO_OF_DAY设置为0.示例示例为

public static void main(String[] args) {
    DateTimeFormatter formatter = 
        new DateTimeFormatterBuilder().appendPattern("yyyyMMdd")
                                      .parseDefaulting(ChronoField.NANO_OF_DAY, 0)
                                      .toFormatter()
                                      .withZone(ZoneId.of("Europe/Berlin"));

    OffsetDateTime offsetDateTime = ZonedDateTime.parse("20151113", formatter).toOffsetDateTime();
    System.out.println(offsetDateTime.format(DateTimeFormatter.ISO_DATE));
}

另一种可能的解决方案是将文本解析为LocalDate,然后用它构建ZoneDateTime

public static void main(String[] args) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
    LocalDate parsed = LocalDate.parse("20151113", formatter);
    ZonedDateTime zonedDateTime = ZonedDateTime.of(parsed, LocalTime.MIDNIGHT, ZoneId.of("Europe/Berlin"));
    // get OffsetDateTime similarly
}

答案 1 :(得分:2)

Java 8 java.time.*包是一个非常严格的包。它不允许类型和输入之间的灵活性 - 如果你想要一个ZonedDateTime对象,你必须从一个具有时区,日期和时间的输入构建它。一段时间。

如果你想使用日期来构建一个对象,那么它必须是一个没有时间字段的类型,特别是LocalDate