Локальный разбор даты и времени - PullRequest
4 голосов
/ 07 октября 2019

Я пытаюсь разобрать входную строку по местному времени.

Ниже приведен мой код

 ZonedDateTime z = ZonedDateTime.parse("2019-11-26T19:30:00Z", MY_DATE_TIME_FORMATTER);

, где

MY_DATE_TIME_FORMATTER= new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(ISO_LOCAL_DATE)
            .appendLiteral('T')
            .append(ISO_LOCAL_TIME)
            .appendLiteral('Z')
            .appendOffset("+HH:mm", "+0000")
            .toFormatter();

Я получаюследующее исключение

java.time.format.DateTimeParseException: текст '2019-11-26T19: 30: 00Z' не может быть проанализирован по индексу 19

Не могли бы вы посоветовать, что я делаюздесь не так?

Ответы [ 3 ]

4 голосов
/ 07 октября 2019

Instant.parse

Шаблон форматирования не требуется.

Instant.parse( "2019-11-26T19:30:00Z" ) 

Ваш формат ввода соответствует стандарту ISO 8601 . Этот конкретный формат имеет Z в конце. Эта буква означает UTC (смещение , равное нулю часов-минут-секунд) и произносится как «зулу».

Класс Instant в java.time представляет момент в UTC, всегда UTC.

Использование класса ZonedDateTime для этого ввода не является наиболее подходящим. У нас есть:

  • Instant для значений, которые всегда в UTC.
  • OffsetDateTime для моментов, когда известно только смещение от UTC, но не часовой пояс. Используйте этот класс и для значений UTC, когда вам нужна большая гибкость, например, для генерации строк в различных форматах. `instant.atOffset (
  • ZonedDateTime для значений в часовом поясе. Часовой пояс - это история прошлых, настоящих и будущих изменений смещения, используемого людьмиопределенного региона.

Table of date-time types in Java, both modern and legacy

Чтобы просмотреть тот же момент, скорректированный с учетом смещения, используемого людьми определенного региона (часового пояса),примените ZoneId, чтобы получить ZonedDateTime объект.

Instant instant = Instant.parse( "2019-11-26T19:30:00Z" ) ;     // Default format for parsing a moment in UTC.
ZoneId z = ZoneId.of( "America/Edmonton" ) ;                    // A time zone is a history of past, present, and future changes to the offset used by the people of a particular region.
ZonedDateTime zdt = instant.atZone( z ) ;                       // Same moment, same point on the timeline, different wall-clock time.

Посмотрите этот код, запущенный в режиме реального времени на IdeOne.com .

instant.toString(): 2019-11-26T19: 30: 00Z

zdt.toString (): 2019-11-26T12: 30-07: 00 [Америка / Эдмонтон]

2 голосов
/ 07 октября 2019

Добавьте

.appendZoneOrOffsetId()

вместо этих двух строк:

.appendLiteral('Z')
.appendOffset("+HH:mm", "+0000")

Весь пример строителя:

MY_DATE_TIME_FORMATTER= new DateTimeFormatterBuilder()
        .parseCaseInsensitive()
        .append(ISO_LOCAL_DATE)
        .appendLiteral('T')
        .append(ISO_LOCAL_TIME)
        .appendZoneOrOffsetId()
        .toFormatter();

PS В вашем конкретном случаеЯ бы предпочел использовать стандартный форматировщик ISO (как упоминал Христо):

ZonedDateTime z = ZonedDateTime.parse("2019-11-26T19:30:00Z", DateTimeFormatter.ISO_ZONED_DATE_TIME);

Более того, метод ZonedDateTime::parse будет работать даже без явного форматера. Так как он используется по умолчанию:

ZonedDateTime z = ZonedDateTime.parse("2019-11-26T19:30:00Z");
1 голос
/ 07 октября 2019

Использовать встроенный ISO зонированный форматер времени

    ZonedDateTime.parse("2019-11-26T19:30:00Z", DateTimeFormatter.ISO_ZONED_DATE_TIME);
...