Как проанализировать смещение с помощью двоеточия, используя DateTimeFormatter?

#java #datetime #parsing #java-8 #dateformatter

#java #дата и время #синтаксический анализ #java-8 #dateformatter

Вопрос:

У меня есть следующая строка: String timeStamp = "2020-01-31 12:13:14 03:00" . И я попытался проанализировать его, используя Java 8 DateTimeFormatter.

 DateTimeFormatter formatter = DateTimeFormatter.ofPattern( format );
tmpTimestamp = ZonedDateTime.parse( timeStamp, formatter );
  

где format находится один из:

 "yyyy-MM-dd' 'HH:mm:ss' 'Z",
"yyyy-MM-dd' 'HH:mm:ss' 'X",
"yyyy-MM-dd' 'HH:mm:ss' 'x",
"yyyy-MM-dd HH:mm:ss Z",
"yyyy-MM-dd HH:mm:ss X",
"yyyy-MM-dd HH:mm:ss x",
  

Ничего не работает. Всегда я получал DateTimeParseException указание либо на символ ‘ ‘, либо на символ ‘:’ в подстроке смещения » 03:00″

Согласно JavaDocs: DateTimeFormatter класса » 03:00″ должен поддерживаться любым из: Z , X и x .

Итак, вопрос в том, как создать строку форматирования для ее анализа?

Комментарии:

1. @MS90 — не LocalDateTime , а скорее OffsetDateTime (поскольку у него есть смещение).

Ответ №1:

Вы должны использовать times X ( yyyy-MM-dd HH:mm:ss XXX ):

 String timeStamp = "2020-01-31 12:13:14  03:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss XXX");
ZonedDateTime tmpTimestamp = ZonedDateTime.parse(timeStamp, formatter);
  

Из документов:

Смещение X и x: это форматирует смещение на основе количества букв шаблона.

Одна буква выводит только час, например ‘ 01’, если только минута не отлична от нуля, и в этом случае также выводится минута, например ‘ 0130’.

Две буквы выводят час и минуту без двоеточия, например ‘ 0130’.

Три буквы выводят час и минуту с двоеточием, например ‘ 01:30’.

Четыре буквы выводят час, минуту и необязательную секунду без двоеточия, например ‘ 013015’.

Пять букв выводят час, минуту и необязательную секунду с двоеточием, например ‘ 01:30:15’.

Шесть или более букв вызывают исключение IllegalArgumentException.

Буква шаблона ‘X’ (верхний регистр) выведет ‘Z’, когда выводимое смещение будет равно нулю, тогда как буква шаблона ‘x’ (нижний регистр) выведет ‘ 00’, ‘ 0000’, или ‘ 00:00’.

В качестве альтернативы вы можете использовать пять букв ( XXXXX ), а также ZZZ или ZZZZZ вместо XXX или XXXXX .

Ответ №2:

Из javadoc

Смещение Z: это форматирует смещение на основе количества букв шаблона. Одна, две или три буквы выводят час и минуту без двоеточия, например ‘ 0130’. На выходе будет ‘ 0000’, когда смещение равно нулю. Четыре буквы выводят полную форму локализованного смещения, эквивалентную четырем буквам смещения-O. На выходе будет соответствующий локализованный текст смещения, если смещение равно нулю. Пять букв выводят час, минуту с необязательной секундой, если она не равна нулю, с двоеточием.Он выводит ‘Z’, если смещение равно нулю. Шесть или более букв вызывают исключение IllegalArgumentException.

Вам нужно 5 нулей

 String format = "yyyy-MM-dd HH:mm:ss ZZZZZ";
  

ДЕМОНСТРАЦИЯ

Ответ №3:

Вам не нужно возиться со строкой шаблона формата.

     DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral(' ')
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .appendLiteral(' ')
            .appendOffsetId()
            .toFormatter();
    String timeStampString = "2020-01-31 12:13:14  03:00";
    OffsetDateTime dateTime = OffsetDateTime.parse(timeStampString, formatter);
    System.out.println(dateTime);
  

Это более многословно, но сложнее ошибиться. Я просто собираю форматер из встроенных частей. Вывод:

2020-01-31T12:13:14 03:00

Я также разбираю в OffsetDateTime вместо ZonedDateTime . Поскольку строка содержит смещение ( 03:00) и не содержит часового пояса (например, America / Boa_Vista), даже если это, вероятно, сработало бы с ZonedDateTime , OffsetDateTime это правильный класс для использования.