【问题标题】:Why does my date time parsing attempt fail?为什么我的日期时间解析尝试失败?
【发布时间】:2018-11-30 08:14:41
【问题描述】:

我正在以两种略有不同的格式解析同一个日期,但遇到了一个我不理解的错误。

标准ISO格式的字符串解析成功:

    String s = "2018-04-17T22:57:29";
    LocalDateTime date = LocalDateTime.parse(s, DateTimeFormatter.ISO_DATE_TIME);  // OK

但是,当我添加 "Z" 后缀并使用 ISO_INSTANT 时:

    s = "2018-04-17T22:57:29Z";
    date = LocalDateTime.parse(s, DateTimeFormatter.ISO_INSTANT); // Fails

我得到以下异常:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2018-04-17T22:57:29Z' could not be parsed: Unable to obtain LocalDateTime from TemporalAccessor: {MicroOfSecond=0, NanoOfSecond=0, MilliOfSecond=0, InstantSeconds=1524005849},ISO of type java.time.format.Parsed
at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1920)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1855)
at java.time.LocalDateTime.parse(LocalDateTime.java:492)
at iplus.fwk.manifest.Test.main(Test.java:37)
Caused by: java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: {MicroOfSecond=0, NanoOfSecond=0, MilliOfSecond=0, InstantSeconds=1524005849},ISO of type java.time.format.Parsed
at java.time.LocalDateTime.from(LocalDateTime.java:461)
at java.time.format.Parsed.query(Parsed.java:226)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
... 2 more
Caused by: java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {MicroOfSecond=0, NanoOfSecond=0, MilliOfSecond=0, InstantSeconds=1524005849},ISO of type java.time.format.Parsed
at java.time.LocalDate.from(LocalDate.java:368)
at java.time.LocalDateTime.from(LocalDateTime.java:456)
... 4 more

我对@9​​87654321@定义的解读 表明第二次解析应该成功。我做错了什么?

【问题讨论】:

    标签: java parsing datetime java-8 java-time


    【解决方案1】:

    我认为正确的想法是这样的:概念上瞬间不是日期和时间。就是这样,一瞬间。它没有时区或偏移量,因此不能有日期和时间。由于LocalDateTime 需要日期和时间,因此即时解析并不能满足您的需求。

    是的,我知道:Instant实现使用自纪元以来的时间,而迄今为止最常见的纪元定义使用 UTC。我还知道您正在解析的字符串包含日期和时间,并且DateTimeFormatter.ISO_INSTANTInstant.toString 都会产生相似的字符串。不过,这是界面,并没有告诉您瞬间的概念是什么。

    我对 ISO_INSTANT 定义的阅读表明第二个 解析应该成功。

    我知道定义可以这样理解。不过,我认为这是值得注意的:

    ...瞬间从 ChronoField.INSTANT_SECONDS 和 ChronoField.NANO_OF_SECOND…

    虽然微秒与 LocalDateTime 等其他日期时间类型共享,但提到的两个字段不足以为您获取 LocalDateTime 的数据。所以这就是它为你打破的地方。要获得LocalDateTime,我们需要假设一个时区或偏移量。即使引用继续:

    …使用 UTC 偏移量。

    ——这仅表示 UTC 偏移量用于计算瞬间秒数和纳秒,而不是在进一步处理中。

    我们也可能会尝试更仔细地研究您的错误消息:

    线程“主”java.time.format.DateTimeParseException 中的异常: 无法解析文本“2018-04-17T22:57:29Z”:无法获取 来自 TemporalAccessor 的 LocalDateTime:{MicroOfSecond=0,NanoOfSecond=0, MilliOfSecond=0,InstantSeconds=1524005849},ISO 类型 java.time.format.Parsed

    这也表明我们从解析中得到的只是瞬间秒数(即自纪元以来的秒数)和秒的分数(以及 ISO 年表)。而且这还不足以获得LocalDateTime

    您不是第一个(也不是最后一个)感到惊讶的人。不过,您观察到的行为是设计使然。

    修复

    ISO_INSTANT的定义还提到:

    ISO_OFFSET_DATE_TIME

    所以这行得通:

        String s = "2018-04-17T22:57:29Z";
        LocalDateTime date = LocalDateTime.parse(s, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    

    结果是2018-04-17T22:57:29(如预期的那样)。

    【讨论】:

    • 感谢您清晰详细的回答。高分!
    猜你喜欢
    • 1970-01-01
    • 2018-05-18
    • 2020-01-05
    • 2021-01-05
    • 2014-05-15
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多