Разбор длинной строки в переменной LocalDate - PullRequest
0 голосов
/ 02 марта 2019

Недавно у меня возникла необходимость взять строку и преобразовать ее в переменную LocalDate в Java;Я знал, что это было возможно и просто, но вот что я не видел:

Контекст: Я использую exiftool для извлечения метаданных из изображения через Java Runtime Execution.Проблема в том, что exiftool предоставляет следующую строку:

2019:02:28 11:37:47-06:00

Это не ваш обычный стандартный формат ISO (или, по крайней мере, я так думаю).Я не знаю, использует ли это какой-либо уже реализованный стандарт форматирования.Итак, чтобы исправить мою проблему, я создал следующий код для ручного разбора:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy:MM:dd HH:mm:ssZ", Locale.ENGLISH);
LocalDate date = LocalDate.parse(VAR_WITH_STR_TO_CONVERT, formatter);

Я думаю, что это хорошая реализация для ручного преобразования, но этот код генерирует следующее исключение:

> Text '2019:02:28 11:37:47-06:00' could not be parsed at index 19
at java.time.format.DateTimeFormatter.parseResolved0(Unknown Source)
at java.time.format.DateTimeFormatter.parse(Unknown Source)
at java.time.LocalDate.parse(Unknown Source)

Я считаю, что проблема заключается в строке формата, которую я предоставляю для преобразования, но, проверяя документы DateTimeFormatter, я думаю, что у меня правильная строка.

yyyy:MM:dd HH:mm:ssZ

У меня нет идей, даКто-нибудь знает проблему здесь?

Ответы [ 2 ]

0 голосов
/ 02 марта 2019

TL; DR Для часового пояса используйте XXX, а не Z, чтобы проанализировать значение, подобное -06:00.


Документация, т.е. javadocDateTimeFormatter, задает:

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

  • Одна буква выводит только час, например, «+01», если только минута не равна нулю, в этом случае также выводится минута, например, «+0130».
  • Вывод двух буквчасы и минуты без двоеточия, такие как «+0130».
  • Три буквы и часа выводят с двоеточием, например «+01: 30».
  • Четыре буквы выводят часы и минуты и необязательную секунду без двоеточия, например '+013015'.
  • Пять букв выводят часы и минуты и необязательную секунду с двоеточием, например '+01: 30: 15'.
  • Шесть или более букв выбрасывают IllegalArgumentException.

Шаблон буквы "X" (заглавные буквы) будетвывод 'Z'когда смещение для вывода будет равно нулю, тогда как буква шаблона' x '(нижний регистр) выведет' +00 ',' +0000 'или' +00: 00 '.

Смещение Z: Форматирует смещение на основе количества букв шаблона.

  • Одна, две или три буквы выводят часы и минутыбез двоеточия, например «+0130».Выход будет равен «+0000», когда смещение равно нулю.
  • Четыре буквы выводят полную форму локализованного смещения, эквивалентного четырем буквам Offset-O.Выводом будет соответствующий локализованный текст смещения, если смещение равно нулю.
  • Пять букв выводят час, минуту, с необязательной секундой, если не ноль, с двоеточием.Он выводит 'Z', если смещение равно нулю.
  • Шесть или более букв выбрасывают IllegalArgumentException.

Как видите, вы использовали 1 Z, что означает -0600.

Чтобы проанализировать часовой пояс с часами и минутами (необязательные секунды), с двоеточиями, вам нужен один из выделенных шаблонов:

XXX      UTC is `Z`.
XXXXX    UTC is `Z`. Optional seconds.
xxx      UTC is `+00:00`
xxxxx    UTC is `+00:00`. Optional seconds.
ZZZZZ    UTC is `Z`. Optional seconds.
0 голосов
/ 02 марта 2019

2019: 02: 28 11: 37: 47-06: 00

Это не ваш обычный стандартный формат ISO

По аналогии с ISO 8601:

  • Замените символ ПРОБЕЛ в середине символом T.
  • Заменить первые два символа COLON дефисами.

Манипуляции со строками

Вы можете сделать это, разделив строку на пробел, заменив первые два двоеточия в первой части, а затем соединив их вместе.

String input = "2019:02:28 11:37:47-06:00";
String[] parts = input.split(" ");
String inputModified = parts[0].replace( ":" , "-" ) + "T" + parts[1] ;

Код форматирования: xxxxx

Или пользовательский шаблон форматирования можно определить с помощью объекта DateTimeFormatter.Используйте пять x кодовых символов для смещения часов-минут и необязательных секунд с разделителями символов COLON.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu:MM:dd HH:mm:ssxxxxx") ;

См. Этот форматер в коде, запущенном в режиме реального времени на IdeOne.com .

OffsetDateTime

LocalDate.parse

Нет, сначала проанализируйте все, а не только часть даты, на случай, если вы найдетеэто ценно в какой-то момент.Анализируйте как OffsetDateTime, так как ваш ввод указывает смещение от UTC (часы-минуты-секунды), но не полный часовой пояс (Continent/Region).

OffsetDateTime odt = OffsetDateTime.parse( input ) ;

Очевидно, вам нужна часть только с датой, без времени суток и без смещения от UTC.Предполагая, что вы хотите указать дату, указанную в этом смещении, просто позвоните toLocalDate.

LocalDate ld = odt.toLocalDate() ;

ld.toString (): 2019-02-28

иливозможно, вы хотите дату, как видно в другом месте.Помните, что в любой данный момент дата и время суток меняются по всему земному шару в зависимости от часового пояса.Это может быть «завтра» в Asia/Japan, в то время как одновременно «вчера» в America/Edmonton.

UTC

Если вы хотите указать дату в UTC:

OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC ) ;
LocalDate ld = odtUTc.toLocalDate() ;

ZonedDateTime

Или, возможно, вы хотите, чтобы дата отображалась в определенном часовом поясе.

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
LocalDate ld = zdt.toLocalDate() ;

Совет. Если вы можете определить источник двоеточий в части даты,ознакомить их со стандартом ISO 8601 .

...