Java Instant.parse на дату Java 8 - PullRequest
3 голосов
/ 22 марта 2019

У меня есть несколько устаревших документов KML, в которых есть отметка времени. Почему указанная ниже дата недействительна при использовании мгновенного анализа Предполагается, что оба метода анализируют даты в формате 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 проанализирован правильно ....

Ответы [ 2 ]

4 голосов
/ 22 марта 2019
  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 игнорирует скачок секунд.Из документов :

Реализации шкалы времени Java с использованием API-интерфейса JSR-310 не обязаны предоставлять любые часы с точностью до одной секунды или монотонно прогрессирующиеили плавно. Реализации поэтому не обязаны фактически выполнять убой UTC-SLS или иным образом знать о високосных секундах .Однако JSR-310 требует, чтобы реализации документировали подход, который они используют при определении часов, представляющих текущий момент.Подробнее о доступных часах см. Часы.

3 голосов
/ 23 марта 2019

Принятый ответ в порядке. Мне просто нужно добавить две вещи:

  1. Вы можете проанализировать строку с недопустимым вторым значением 60, используя ResolverStyle.LENIENT.
  2. Поскольку Джон Скит в комментарии упомянул о возможной дополнительной секунде: это недопустимая дополнительная секунда. 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

Я не знаю, почему это должно быть так сложно, но это работает.

Ссылка: Документация DateTimeFormatter.parsedLeapSecond

...