Java: DateTimeFormatter не может проанализировать строку времени, когда все секунды и миллисекунды равны 0?
В основном, я использую следующий код для разбора строки как LocalDateTime, которая работает в большинстве случаев.
DateTimeFormatter dtformatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
Однако я сталкиваюсь со случаями, когда секунды и миллисекунды 00000
и это когда синтаксический анализатор не удается и распечатать LocalDateTime
2018-03-01T09:16
вместо 2018-03-01T09:16:00.000
,
System.out.println(LocalDateTime.parse("20180301091600000",dtformatter));
(Обратите внимание, что в моем коде, я должен проанализировать строку как LocalDateTime
, сделайте некоторое сравнение и затем в конце напечатайте LocalDateTime
в CSV)
Как я могу это исправить, чтобы сделать его печатным 2018-03-01T09:16:00.000
вместо 2018-03-01T09:16
?
К вашему сведению, я использую jdk10.
3 ответа
Я не уверен, почему это не работает, кажется, это ошибка, потому что, когда я использую:
20180301091600001 result is 2018-03-01T09:16:00.001
----------------^ -----------------^^^^^^
Также еще один тест:
2018030100000000 result is 2018-03-01T00:00
--------^^^----- -----------^^^^^^^^^^^
Кажется, что парсер игнорирует секунды и миллисекунды, когда он равен нулю, почему?
Полное объяснение почему?, в ответе Василия Бурка.
Решение
Вот быстрое исправление, где вы можете использовать другой форматтер, как это:
var result = LocalDateTime.parse("20180301091600000", dtformatter)
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS"));
Выход
2018-03-01T09:16:00:000
ТЛ; др
где секунды и миллисекунды равны 00000, и это когда происходит сбой синтаксического анализатора
Нет, парсер успешен. Ваша проблема с генерацией строки, а не с ее разбором.
По умолчанию DateTimeFormatter
подавляет нулевые значения в секундах и доли секунды, как задокументировано.
Особенность, а не ошибка
Ваша проблема не в разборе, а в генерации строки после разбора. Имейте в виду, что текстовое представление объекта даты и времени отличается от объекта. Другими словами, объект даты и времени не имеет "формата".
[Строка] ->
parse
-> [LocalDateTime] ->toString
-> [Строка]
Документация для LocalDateTime::toString
ясно говорит, что кратчайшие возможные варианты форматирования будут использоваться при обнаружении нулевых значений в наименее значимых частях. Цитировать:
Выходные данные будут в одном из следующих форматов ISO-8601:
уууу-ММ-dd'T'HH: мм
уууу-ММ-dd'T'HH: мм: сс
уууу-ММ-dd'T'HH: мм: СС.ссс
уууу-ММ-dd'T'HH: мм: ss.SSSSSS
уууу-ММ-dd'T'HH: мм: ss.SSSSSSSSS
Используемый формат будет самым коротким, который выводит полное значение времени, когда пропущенные части подразумеваются равными нулю.
Примеры
Относительно двух примеров, показанных в принятом Ответе YCF_L …
20180301091600001 - 2018-03-01T09:16:00.001
В этом примере наименее значимая часть (миллисекунда) имеет ненулевое значение, поэтому она представлена в результате.
2018030100000000 результат - 2018-03-01T00:00
В этом примере наименее значимые части часа, минуты, секунды, миллисекунды, микросекунды и наносекунды равны нулю. Таким образом, их отображение подавляется, за исключением часов и минут, поскольку документация обещает, что год-минута всегда отображается.
Так что оба ваших примера работают как задокументировано; особенность, а не ошибка.
Решение
Решение состоит в том, чтобы не использовать форматтер по умолчанию, предоставленный в toString
метод. Вместо этого используйте другой форматер. Например, используйте тот же пользовательский форматер, который вы определили для анализа.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "yyyyMMddHHmmssSSS" );
LocalDateTime ldt = LocalDateTime.parse( "20180301091600000" , f );
String outputDefault = ldt.toString();
String outputCustom = ldt.format( f );
Дамп на консоль.
System.out.println( "outputDefault: " + outputDefault );
System.out.println( "outputCustom: " + outputCustom );
outputDefault: 2018-03-01T09: 16
outputCustom: 20180301091600000
Вопрос задает:
Как я могу исправить это, чтобы он печатал 2018-03-01T09:16:00.000 вместо 2018-03-01T09:16?
Укажите пользовательский форматер вместо стандартного.
DateTimeFormatter f = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS") ;
String output = ldt.format( f ) ;
Но имейте в виду, что ваша сгенерированная строка будет подавлять отображение любых микросекунд или наносекунд в LocalDateTime
объект.
@BasilBourque У меня есть еще вопрос к вам, ответ выше
Когда мы анализируем это в OffsetDateTime, у меня есть дата «2023-12-10T00:00:00.000». Анализируемый объект OffsetDateTime никогда не имеет секунд и наносекунд. можем ли мы как-нибудь добавить секунды и нано в объект OffsetDateTime? Пожалуйста, ознакомьтесь с прикрепленным фрагментом кода и информацией об отладке.