Instant.parse 和 RFC3339 字符串抛出 java.time.format.DateTimeParseException

Instant.parse and RFC3339 string throws java.time.format.DateTimeParseException

如果我这样做

import java.time.Instant;
...
    Instant instant = Instant.parse("2018-01-02T18:14:59.000+01:00")

我得到这个异常:

Caused by: java.time.format.DateTimeParseException: Text '2018-06-19T23:00:00.000+01:00' could not be parsed at index 23
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1777)

但如果我这样做

    Instant instant = Instant.parse("2018-06-19T23:00:00.000Z");

一切正常。

我想念什么?第一次字符串有什么问题?

原因是您的第一个 String 不符合 parse 方法可接受的格式


正如 Instant#parse(CharSequence text) 的文档所述:

The string must represent a valid instant in UTC and is parsed using DateTimeFormatter.ISO_INSTANT

DateTimeFormatter#ISO_INSTANT 的文档指出:

The ISO instant formatter that formats or parses an instant in UTC, such as '2011-12-03T10:15:30Z'.


要从您的字符串中获取 Instant,您需要:Workable Demo

String str = "2018-01-02T18:14:59.000+01:00";
Instant instant = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(str, Instant::from);

您的日期字符串包含区域信息。 ISO_INSTANT(Instant::parse 方法的默认格式)不处理这个问题。而是使用

Instant instant = DateTimeFormatter.ISO_ZONED_DATE_TIME.parse(date, Instant::from);

现在 JDK 12 及更高版本可以解析它,而 JDK <= 11 则不能。 DateTimeFormatter.ISO_INSTANT 的 Java 12 Javadoc 添加了以下新句子:

When parsing, the behaviour of DateTimeFormatterBuilder.appendOffsetId() will be used to parse the offset, converting the instant to UTC as necessary.

确实,相应的 JDK 错误 (JDK-8166138) 显示修复从 Java 12.

开始可用

例如(来自here),

$ docker run --rm -it openjdk:14-jdk
Apr 27, 2020 2:28:44 PM java.util.prefs.FileSystemPreferences run
INFO: Created user preferences directory.
|  Welcome to JShell -- Version 14.0.1
|  For an introduction type: /help intro

jshell> java.time.Instant.parse("2020-04-21T13:22:10.836777828-07:00");
 ==> 2020-04-21T20:22:10.836777828Z

jshell>