为什么我的日期时间解析尝试失败?
Why does my date time parsing attempt fail?
我正在用两种略有不同的格式解析同一日期,但遇到了一个我无法理解的错误。
解析标准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
我对ISO_INSTANT定义的解读
建议第二次解析应该成功。我做错了什么?
我认为正确的思考方式是这样的:概念上瞬间不是日期和时间。只是,一瞬间。它没有时区或偏移量,因此不能有日期和时间。由于 LocalDateTime
需要日期和时间,即时解析并不能满足您的需求。
是的,我知道:Instant
的 实现 使用自纪元以来的时间,而迄今为止最常见的纪元定义使用 UTC。我还知道您正在解析的字符串包含日期和一天中的时间,并且 DateTimeFormatter.ISO_INSTANT
和 Instant.toString
都会产生相似的字符串。不过,这是界面,并没有告诉你瞬间的概念是什么。
My reading of the definition of ISO_INSTANT suggests that the second
parse should succeed.
我知道定义可以这样读。不过,我认为这值得注意:
…the instant is converted from ChronoField.INSTANT_SECONDS and
ChronoField.NANO_OF_SECOND…
虽然 nano of second 与 LocalDateTime
等其他日期时间类型共享,但上述两个字段不足以让您获得 LocalDateTime
的数据。所以这就是它为你打破的地方。要获得 LocalDateTime
,我们需要假设一个时区或偏移量。尽管引用还在继续:
…using the UTC offset.
—这仅表示UTC偏移用于计算瞬间秒和纳秒,而不用于进一步处理。
我们也可能会尝试更仔细地研究您的错误消息:
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
这也说明我们从解析中得到的只是瞬间秒数(即自纪元以来的秒数)和秒数的分数(以及 ISO 年表)。而且这还不足以获得 LocalDateTime
.
您不是第一个(也不是最后一个)感到惊讶的人。不过,您观察到的行为是设计使然。
修复
ISO_INSTANT
的定义还提到:
The 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
(符合预期)。
我正在用两种略有不同的格式解析同一日期,但遇到了一个我无法理解的错误。
解析标准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
我对ISO_INSTANT定义的解读 建议第二次解析应该成功。我做错了什么?
我认为正确的思考方式是这样的:概念上瞬间不是日期和时间。只是,一瞬间。它没有时区或偏移量,因此不能有日期和时间。由于 LocalDateTime
需要日期和时间,即时解析并不能满足您的需求。
是的,我知道:Instant
的 实现 使用自纪元以来的时间,而迄今为止最常见的纪元定义使用 UTC。我还知道您正在解析的字符串包含日期和一天中的时间,并且 DateTimeFormatter.ISO_INSTANT
和 Instant.toString
都会产生相似的字符串。不过,这是界面,并没有告诉你瞬间的概念是什么。
My reading of the definition of ISO_INSTANT suggests that the second parse should succeed.
我知道定义可以这样读。不过,我认为这值得注意:
…the instant is converted from ChronoField.INSTANT_SECONDS and ChronoField.NANO_OF_SECOND…
虽然 nano of second 与 LocalDateTime
等其他日期时间类型共享,但上述两个字段不足以让您获得 LocalDateTime
的数据。所以这就是它为你打破的地方。要获得 LocalDateTime
,我们需要假设一个时区或偏移量。尽管引用还在继续:
…using the UTC offset.
—这仅表示UTC偏移用于计算瞬间秒和纳秒,而不用于进一步处理。
我们也可能会尝试更仔细地研究您的错误消息:
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
这也说明我们从解析中得到的只是瞬间秒数(即自纪元以来的秒数)和秒数的分数(以及 ISO 年表)。而且这还不足以获得 LocalDateTime
.
您不是第一个(也不是最后一个)感到惊讶的人。不过,您观察到的行为是设计使然。
修复
ISO_INSTANT
的定义还提到:
The
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
(符合预期)。