Проблема формата даты с DateTimeFormatter
У меня дата в следующем формате:
1/1/2020 3:4:7 AM
Я пытаюсь отформатировать его с помощью
DateTimeFormatter
.
У меня есть следующий код с форматировщиком для его анализа, но он не работает.
LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));
У меня следующее исключение:
java.time.format.DateTimeParseException: Text '1/1/2020 3:4:7 AM' could not be parsed at index 0
Может кто-нибудь мне помочь?
4 ответа
Две отдельные проблемы:
Неправильный подсчет
Вы используете, например,
MM
который является явным: всегда полное количество цифр с нулями. Ваша строка не такая, это просто число. Итак, сделайте это
M/d/uuuu h:m:s a
.
РЕДАКТИРОВАТЬ: изменено
yyyy
к
uuuu
, спасибо, @deHaar. Обоснование: гггг или уууу редко имеют значение, но учтите, что это означает, что требуется4 цифры. Разница начинается за годы до 0:
uuuu
идет отрицательно,
yyyy
не использует и ожидает от вас, например,
GG
так что вы получите
44 BC
вместо
-44
. По тому пути,
uuuu
просто более правильно, хотя обычно разница не возникает.
Отсутствует локаль
Вторая проблема заключается в том, что вам практически никогда не следует использовать эту версию
ofPattern
- в нем есть ошибка, которую нельзя отловить с помощью модульных тестов, что делает ее в тысячи раз "тяжелее" и, следовательно, реальной проблемой.
Вам нужно указать локаль. Без него AM не будет анализировать, если локаль вашей платформы по умолчанию не является английской.
Собираем все вместе
LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM",
DateTimeFormatter.ofPattern("M/d/uuuu h:m:s a", Locale.ENGLISH));
работает отлично.
Используйте отдельные буквы для компонентов даты и времени (месяц, день, год, час, минута и секунда).
Вы также можете заставить форматер обрабатывать шаблон без учета регистра (например, am, AM, Am), как показано ниже:
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.util.Locale; public class Main { public static void main(String[] args) { // Formatter to handle the pattern in case insensitive way (e.g. am, AM, Am) DateTimeFormatter formatter = new DateTimeFormatterBuilder() .parseCaseInsensitive() .appendPattern("M/d/u h:m:s a") .toFormatter(Locale.ENGLISH); LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM", formatter); System.out.println(date); } }
Вывод:
2020-01-01T03:04:07
В вашем фрагменте:
LocalDateTime
.parse("1/1/2020 3:4:7 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));
1
- не соответствуетMM
1
- не соответствуетdd
3
- не соответствуетhh
4
- не соответствуетmm
7
- не соответствуетss
т.е. длины частей шаблона форматтера (например,
MM
) и их соответствующие части из текста строки (например,
1
) не соответствовать.
Вы можете сопоставить их несколькими способами, например, вы можете либо изменить текст строки, чтобы он соответствовал шаблону форматирования, либо наоборот.
Вместо этого вы можете попробовать следующее:
LocalDateTime
.parse("01/01/2020 03:04:07 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));
Кроме того, обратите внимание на буквы и символы образца.
Согласно документации DateTimeFormatter:
Число: если количество букв равно единице, то значение выводится с использованием минимального количества цифр и без заполнения. В противном случае в качестве ширины выходного поля используется количество цифр, при необходимости значение дополняется нулями.
Изменив рассуждения, вы можете попробовать использовать вместо этого этот форматировщик:
DateTimeFormatter.ofPattern("M/d/yyyy h:m:s a")