Как разобрать дату JSR-310 в Instant? - PullRequest
1 голос
/ 12 февраля 2020

Я пытаюсь разобрать, скажем, "2020-01-12+01:00" со временем JSR-310.

Я читаю это через DateTimeFormatter.ofPattern("yyyy-MM-ddVV"), однако теперь, если я хочу преобразовать это в Мгновенное действие через Instant.from(DateTimeFormatter.ofPattern("yyyy-MM-ddVV").parse("..."), он выдает, где жалуется, что time равно нулю.

Что предоставлено это так, но я хотел бы получить Instant от этого, то есть epochMillis, чтобы я мог сериализовать long в базу данных.

Есть ли способ обойти это? По сути, я хотел бы расширить "2020-01-12+01:00" до "2020-01-12T00:00.000+01:00" и разобрать его в Instant как обычно

Ответы [ 3 ]

2 голосов
/ 12 февраля 2020

Вам необходимо использовать DateTimeFormatterBuilder, указав ISO_DATE формат и по умолчанию время суток (полночь 1 ):

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
        .append(DateTimeFormatter.ISO_DATE)
        .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
        .toFormatter();
Instant instant = Instant.from(formatter.parse("2020-01-12+01:00"));
System.out.println(instant);

1) ChronoField может быть любым полем дня , т. Е. HOUR_OF_DAY, CLOCK_HOUR_OF_DAY, MINUTE_OF_DAY, SECOND_OF_DAY, MILLI_OF_DAY, MICRO_OF_DAY или NANO_OF_DAY.

Выход

2020-01-11T23:00:00Z

Если вы хотите сохранить смещение часового пояса, вам нужно использовать OffsetDateTime (или ZonedDateTime) вместо Instant:

OffsetDateTime dateTime = OffsetDateTime.parse("2020-01-12+01:00", formatter);
System.out.println(dateTime);
System.out.println(dateTime.format(DateTimeFormatter.ISO_DATE));

Вывод (как из OffsetDateTime, так и из ZonedDateTime)

2020-01-12T00:00+01:00
2020-01-12+01:00
0 голосов
/ 13 февраля 2020

Достаточно легко, когда знаешь как. Нам нужен встроенный форматер. Сложность в том, что нет типа для разбора строки, нет OffsetDate. Я представляю два варианта решения этой проблемы.

    String s = "2020-01-12+01:00";

    TemporalAccessor parsed = DateTimeFormatter.ISO_OFFSET_DATE.parse(s);
    LocalDate date = LocalDate.from(parsed);
    ZoneOffset offset = ZoneOffset.from(parsed);
    Instant result = date.atStartOfDay(offset).toInstant();

    System.out.println(result);

Вывод этого фрагмента:

2020-01-11T23: 00: 00Z

Нам редко нужно напрямую использовать интерфейс TemporalAccessor, и он считается низкоуровневым. Это также не единственный способ go здесь. Другим хорошим вариантом является определение времени суток по умолчанию, чтобы мы могли выполнить синтаксический анализ непосредственно в Instant:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_OFFSET_DATE)
            .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
            .toFormatter();
    Instant result = formatter.parse(s, Instant::from);

Результат такой же, как и раньше.

0 голосов
/ 12 февраля 2020

Вы можете использовать LocalDate.parse(dateString, formatter), используя Formatter, который вы сделали выше, чтобы дать вам LocalDate экземпляр.

LocalDate может затем дать вам LocalDateTime в любое время в этом день, но (например) вы можете получить начало дня из него.

LocalDateTime имеет метод toInstant, чтобы дать вам Instant.

Instant имеет метод toEpochMilli для получения long.

...