Java Instant.parse 日期 java 8

Java Instant.parse on Date java 8

我有一些包含时间戳条目的旧版 KML 文档。 为什么使用 Instant 解析时以下日期无效?这两种方法都假设解析 ISO 8601 格式的日期。

String dateString = "2017-12-04T08:06:60Z"

使用

java.time.Instant.parse(dateString)

引发错误

"DateTimeParseException Text 2017-12-04T08:06:60Z could not be parsed at index 0."

但是,当使用

Date myDate =   javax.xml.bind.DatatypeConverter.parseDateTime( dateString )

myDate 被正确解析....

  1. 60 秒不是有效时间。这意味着这是无效的 2017-12-04T08:06:60Z,如果它是 60 秒,那么分钟应该增加并且 你的 时间将是 2017-12-04T08:07:00Z
  2. 使用有效日期然后解析 String 就可以了:

    String date = "2017-12-04T08:07:00Z";
    System.out.println(Instant.parse(date));
    

同时 java.time 忽略 leap 秒。来自 docs:

Implementations of the Java time-scale using the JSR-310 API are not required to provide any clock that is sub-second accurate, or that progresses monotonically or smoothly. Implementations are therefore not required to actually perform the UTC-SLS slew or to otherwise be aware of leap seconds. JSR-310 does, however, require that implementations must document the approach they use when defining a clock representing the current instant. See Clock for details on the available clocks.

接受的答案很好。我只有两件事要补充:

  1. 可以 使用ResolverStyle.LENIENT.
  2. 解析具有无效第二个值60 的字符串
  3. 由于 Jon Skeet 在评论中提到了可能的闰秒:这不是有效的闰秒。 java.time 支持解析(有效的)闰秒。

正在解析您的字符串

    DateTimeFormatter lenientFormatter
            = DateTimeFormatter.ISO_OFFSET_DATE_TIME
                    .withResolverStyle(ResolverStyle.LENIENT);
    String dateString = "2018-12-04T08:06:60Z";
    Instant myInstant = lenientFormatter.parse(dateString, Instant::from);
    System.out.println(myInstant);

输出:

2018-12-04T08:07:00Z

因此溢出的秒值 60 已滚入整整一分钟。

顺便说一句,javax.xml.bind.DatatypeConverter.parseDateTime 解析为 Calendar(不是 Date),这就是返回的对象实际上可以保存第二个值 60 的方式。看起来它通常接受第二个值 60,但在 61 时抛出异常。

解析有效闰秒

这并不能回答您的问题,但我认为它可能对未来的读者有用。闰秒始终是当天的最后一秒,因此 23:59:60。一个Instant不能持有这个值,但是你可以查询一个是否被解析。通过 DateTimeFormatterBuilder.appendInstant(),DateTimeFormatter.parsedLeapSecond().

支持
    DateTimeFormatter leapSecondFormatter = new DateTimeFormatterBuilder()
            .appendInstant()
            .toFormatter();
    Instant myInstant
            = leapSecondFormatter.parse("2018-12-04T23:59:60Z", Instant::from);
    System.out.println(myInstant);

    TemporalAccessor parsed = leapSecondFormatter.parse("2018-12-04T23:59:60Z");
    System.out.println("Instant: " + parsed.query(Instant::from));
    System.out.println("Was a leap second parsed? "
            + parsed.query(DateTimeFormatter.parsedLeapSecond()));

输出:

2018-12-04T23:59:59Z
Instant: 2018-12-04T23:59:59Z
Was a leap second parsed? true

我不知道为什么要这么复杂,但它确实有效。

Link: Documentation of DateTimeFormatter.parsedLeapSecond