Разбор ISO_INSTANT и подобных строк даты и времени

Я создал этот замечательный статический метод вчера, и он отлично работал - вчера

Однако сегодня он дает мне эту ошибку. Я предполагаю, что это из-за слишком большого количества 0 перед Z.

Может ли кто-нибудь порекомендовать, как кратко разобрать (Java 8) этот тип даты формата String, помня, что он работал и вчера, поэтому ISO_INSTANT также является допустимым форматом для String?

Caused by: java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {NanoOfSecond=0, InstantSeconds=1443451604, MilliOfSecond=0, MicroOfSecond=0},ISO of type java.time.format.Parsed
at java.time.LocalDate.from(LocalDate.java:368)
at java.time.LocalDateTime.from(LocalDateTime.java:456)
... 9 more

исключение во время ввода: "2015-09-28T14:46:44.000000Z"

/**
 *
 * @param time the time in RFC3339 format (e.g. "2013-07-03T14:30:38Z" )
 * @return
 */
public static LocalDateTime parseTimeINSTANT(String time) {
    DateTimeFormatter f = DateTimeFormatter.ISO_INSTANT;
    return LocalDateTime.from(f.parse(time));
}

введите описание изображения здесь


person ycomp    schedule 28.09.2015    source источник
comment
ISO_INSTANT не поддерживает часовые пояса, это можно исправить с помощью чего-то вроде: Instant.from(DateTimeFormatter.ISO_DATE_TIME.parse("2017-04-20T00:00:00+04:00"))   -  person Pavel Evstigneev    schedule 11.04.2017


Ответы (4)


Вы анализируете строку, которая соответствует моменту ISO, поэтому вам нужно сохранить результат в Instant вместо LocalDateTime:

public static Instant parseTimeINSTANT(String time) {
    DateTimeFormatter f = DateTimeFormatter.ISO_INSTANT;
    return Instant.from(f.parse(time)); // could be written f.parse(time, Instant::from);
}

Обратите внимание, что этот модуль форматирования правильно обрабатывает дробные секунды, поэтому вам не нужно их удалять. Цитирование DateTimeFormatter.ISO_INSTANT Javadoc (выделено мой):

При синтаксическом анализе требуется время хотя бы до поля секунд. Разбираются доли секунды от нуля до девяти.

Почему это работало вчера, а не сегодня, я понятия не имею...

person Tunaki    schedule 28.09.2015
comment
спасибо, а можно сделать LocalDateTime.from(instant); ? мой код действительно ожидает формат LocalDateTime. наносекунды не важны - person ycomp; 28.09.2015
comment
@ycomp Вы можете преобразовать Instant в LocalDateTime, см. этот ответ. - person Tunaki; 28.09.2015
comment
возможно, я просто закодировал его вчера, думал, что запустил его, но никогда не запускал его до сегодняшнего дня - я не вижу в своем коде ничего, что указывало бы на то, что я смог бы запустить его вчера ... так что я думаю, что на самом деле это никогда не работало так, как я изначально закодировал это - person ycomp; 28.09.2015

Просто для того, чтобы помочь любому, кто увидит этот вопрос позже.

Вам нужно проанализировать дату ISO как Instant, преобразовать ее в объект Instant, а затем создать из нее LocalDateTime, указав идентификатор зоны. Я устанавливаю идентификатор зоны UTC здесь.

Код выглядит следующим образом

public static LocalDateTime getISODate(String dateString) {
    DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_INSTANT;
    Instant dateInstant = Instant.from(isoFormatter.parse(dateString));
    LocalDateTime date = LocalDateTime.ofInstant(dateInstant, ZoneId.of(ZoneOffset.UTC.getId()));

    return date;
}
person Ahmed Kamal    schedule 25.11.2015
comment
В качестве примечания: вы можете использовать более короткую форму, например: LocalDateTime.ofInstant(dateInstant, ZoneOffset.UTC), то есть без получения ZoneId явно, потому что ZoneOffset (в данном случае это ZoneOffset.UTC) расширяет ZoneId. - person informatik01; 04.11.2019
comment
Применяя ярлык, упомянутый informatik01, вы попадаете в эту строку: LocalDateTime date = LocalDateTime.ofInstant(dateInstant, ZoneOffset.UTC); - person Robert; 25.09.2020

You do not need a DateTimeFormatter

Разберите строку даты и времени, соответствующую стандарту ISO 8601, непосредственно в Instant, используя Instant#parse. Современный API даты и времени основан на ISO 8601 и не требует явного использования объекта DateTimeFormatter. если строка даты и времени соответствует стандартам ISO 8601.

Демонстрация:

import java.time.Instant;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.parse("2015-09-28T14:46:44.000000Z");
        System.out.println(instant);
    }
}

Вывод:

2015-09-28T14:46:44Z

ОНЛАЙН-ДЕМО

What if I want LocalDateTime at UTC?

Instant можно преобразовать в другие типы java.time, например.

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.parse("2015-09-28T14:46:44.000000Z");
        System.out.println(instant);

        LocalDateTime ldt = instant.atZone(ZoneOffset.UTC).toLocalDateTime();
        System.out.println(ldt);
    }
}

Вывод:

2015-09-28T14:46:44Z
2015-09-28T14:46:44

ОНЛАЙН-ДЕМО

Узнайте больше о современном API Date-Time на странице Trail: Date Time< /а>.

person Arvind Kumar Avinash    schedule 23.07.2021

ISO_INSTANT не имеет информации о зоне. Просто добавьте это. Или используйте DateTimeFormatter.ISO_ZONED_DATE_TIME вместо этого

import java.time.*;
import java.time.format.*;

public class TestMain {

    DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT.withZone(ZoneId.of("Z"));

    DateTimeFormatter formatter2 = DateTimeFormatter.ISO_ZONED_DATE_TIME

    public static void main(String[] args) {
        ZonedDateTime.parse("2031-12-01T10:58:30Z", formatter);
        ZonedDateTime.parse("2031-12-01T10:58:30Z", formatter2);
    }
}
person Valchkou    schedule 23.07.2021