Ваш пример шаблона форматирования не подходит для класса DateTimeFormatter
.Например, заглавные буквы YYYY
означают недельный год, что, скорее всего, не является намерением отправителя.DD
означает день года (1-366), опять же маловероятно намерение отправителя.
DateTimeFormatter
коды форматирования
Вам нужно будет узнать кодыперешел к вам в такие строки.Затем вам нужно будет перевести на соответствующие коды шаблонов форматирования, используемые классом DateTimeFormatter
.
DateTimeFormatterBuilder
Вероятно, вы выиграете от использования очень гибкогои мощный DateTimeFormatterBuilder
класс, где вы можете создать формат несколькими вызовами.После всех необходимых вызовов вы, наконец, генерируете DateTimeFormatter
, вызывая DateTimeFormatterBuilder::toFormatter
.
Поиск переполнения стека для примеров использования этого класса.
Другие проблемы
как определить, содержит ли строка шаблона информацию о часовом поясе
Z
в переданном коде форматирования говорит вам.
Я могу добавить .withZone (ZoneOffset.UTC)
Если вы пытаетесь настроить на UTC, сделайте это после , когда вы проанализироваливходная строка в объект даты и времени.Чтобы добраться до UTC, просто позвоните toInstant
, так как Instant
всегда в UTC, по определению.
Я не настраиваюсь на UTC, я хочу установить зону как UTC, еслив шаблоне не указана зона.
Если во входной строке отсутствует какой-либо индикатор часового пояса или смещения от UTC, выполните синтаксический анализ LocalDateTime
.В этом классе намеренно отсутствует понятие часового пояса или смещения от UTC.Таким образом, LocalDateTime
не представляет момент, является не точкой на временной шкале.
Если вы точно знаете строку без зоны / смещениядействительно был предназначен для конкретной зоны / смещения, тогда:
С OffsetDateTime
или ZonedDateTime
у вас теперь есть момент, момент времени.
Что такоеразница между зоной и смещением?Смещение - это просто количество часов-минут-секунд, не более того.Зона, напротив, на намного * на 1094 * больше.Зона - это история прошлых, настоящих и будущих изменений в смещении, используемом людьми определенного региона.
LocalDateTime ldt = LocalDateTime.parse( "2018-01-23T01:23:45.123" ) ; // *Not* a moment, *not* a point on the timeline.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ; // Assign an offset to determine a moment.
Вы, кажется, слишком сосредоточены на синтаксическом анализе как способе применения вашей бизнес-логики.Вместо этого делает ваш анализ как можно более простым и прямым , чтобы получить объект java.time, соответствующий вводу.Только после синтаксического анализа необходимо вносить изменения или преобразования в значение даты-времени.Наконец, отделите и этот код анализа и преобразования от других ваших работ бизнес-логики, так что у вас есть три отдельных этапа: (1) простой / прямой анализ, (2) настройка / преобразование значения, (3) использование значения даты и времени для бизнес-целей.
ISO 8601
Ваш проект сопряжен с рисками.Я бы просто отказался брать на себя ответственность за чужие произвольные строковые вводы с помощью своих собственных придуманных кодов форматирования.Успех или неудача находятся вне вашего контроля, так как вы, возможно, никогда не узнаете полностью, что произойдет.
Более разумный подход заключается в переносе бремени на источник этих входящих данных.Они должны передавать ваши строки в стандартном формате ISO 8601 .Этот стандарт был разработан именно для этой цели, обмениваясь значениями даты и времени в виде текста.Стандартные форматы продуманы так, чтобы быть однозначными, их было легко проанализировать на машине, а также легко прочитать людям в разных культурах.
Классы java.time по умолчанию используют стандартные форматы ISO 8601 при разборе / генерации строк.Класс ZonedDateTime
разумно расширяет стандарт, добавляя название часового пояса в квадратных скобках.Я бы посоветовал источнику ваших данных сделать то же самое при отправке зонированного значения - обычно лучше всего обмениваться только значениями UTC.