首页 > 解决方案 > 无法从 TemporalAccessor 获取 ZoneOffset:{},ISO,Europe/Berlin 解析为 java.time.format.Parsed 类型的 2019-12-26

问题描述

我正在尝试将字符串解析为OffsetDateTime但收到以下错误:

Unhandled exception.
java.time.format.DateTimeParseException: Text '26122019' could not be parsed: Unable to obtain OffsetDateTime from TemporalAccessor: {},ISO,Europe/Berlin resolved to 2019-12-26 of type java.time.format.Parsed

我尝试解析的字符串示例看起来像26122019,数据库中的值看起来像2018-08-31.

在为这些值编写 JPA 查询时,我收到了另一个错误,导致我走上了这条路@Param("filterEndDate") OffsetDateTime filterEndDate,

      DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyyyy").withZone(ZoneId.of("Europe/Berlin"));
    OffsetDateTime fromDate = OffsetDateTime.parse(filterFromDate,formatter);
    OffsetDateTime toDate = OffsetDateTime.parse(filterEndDate,formatter);

然后我调整了我的代码

DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("ddMMyyyy")
            .parseDefaulting(ChronoField.NANO_OF_DAY, 0)
            .toFormatter()
            .withZone(ZoneOffset.UTC);

并得到以下错误:

Caused by: java.time.DateTimeException: Unable to obtain OffsetDateTime from TemporalAccessor: {InstantSeconds=1577318400},ISO,Z resolved to 2019-12-26T00:00 of type java.time.format.Parsed

-----更新1----

代码

LocalDate fromDate = LocalDate.parse(filterFromDate,DateTimeFormatter.ofPattern("ddMMyyyy"));

错误

java.time.format.DateTimeParseException: Text '2019-12-20' could not be parsed at index 2

标签: javaspring-bootdatetimejpa

解决方案


我展示了两种方式。

解析为 LocalDate 并转换

对我来说,简单的方法是这样的:

    String filterFromDate = "26122019";
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ddMMyyyy");
    OffsetDateTime fromDate = LocalDate.parse(filterFromDate, formatter)
            .atStartOfDay(ZoneOffset.UTC)
            .toOffsetDateTime();
    System.out.println(fromDate);

此片段的输出是:

2019-12-26T00:00Z

由于您的字符串包含日期,没有时间并且没有偏移量,因此我正在解析为LocalDate. 然后我执行转换为OffsetDateTime之后。

调整您的高级格式化程序以完成工作

只需简单调整即可使您尝试的方式生效:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("ddMMyyyy")
            .parseDefaulting(ChronoField.NANO_OF_DAY, 0)
            .parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
            .toFormatter();
    OffsetDateTime fromDate = OffsetDateTime.parse(filterFromDate, formatter);

结果和以前一样。java.time 区分偏移量和时区。在许多地方,可以在需要时区的地方使用偏移量,但在这里不行。您的调用withZone()提供了默认时区,但没有默认偏移量。相反,我.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)用来建立默认偏移量。


推荐阅读