Java 8 DateTime API строка разбора даты, когда шаблон и значение неизвестны - PullRequest
0 голосов
/ 11 декабря 2018

У меня есть требование проанализировать неизвестную строку даты и времени, используя также неизвестный, но предоставленный формат даты и времени.Я хочу разобрать на ZonedDateTime.Если в строке шаблона нет зоны, я хочу предположить часовой пояс UTC.Проблема в том, что я не уверен, как определить, содержит ли строка шаблона информацию о часовом поясе, чтобы я мог добавить .withZone(ZoneOffset.UTC) при создании DateTimeFormatter.Как это сделать?

String dateTimeFormat = "yyyy-MM-dd HH:mm:ss Z"; // this will be unknown (could be any possible valid pattern)
String dateTimeValue = "2001-01-01 00:00:00 -0800"; // this will also be unknown

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateTimeFormat);
if(????) { // how to determine if the pattern contains timezone information
    dateTimeFormatter = dateTimeFormatter.withZone(ZoneOffset.UTC);
}

ZonedDateTime dateTime = ZonedDateTime.parse(dateTimeValue, dateTimeFormatter);

Ответы [ 3 ]

0 голосов
/ 11 декабря 2018

Ваш пример шаблона форматирования не подходит для класса 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.

0 голосов
/ 11 декабря 2018

Нет необходимости в if вообще. Как описано в документе Java , «зона переопределения» применяется, только если в тексте не найдено ни одной зоны.(Что делает выбор слова override несколько странным, но это скорее с точки зрения форматирования, чем анализа).

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

Также, кстати, DateTimeFormatter является неизменным классом.В вашем примере withZone ничего не сделает, потому что вы отбросили возвращаемый объект.

0 голосов
/ 11 декабря 2018

Один из способов определить, разбирается ли данная дата с использованием ZonedDateTime.Если он не может быть проанализирован, у него нет информации о часовом поясе.

  DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateTimeFormat);

    ZonedDateTime zonedDateTime = null;
    try{
      zonedDateTime  = ZonedDateTime.parse(dateTimeValue, dateTimeFormatter);
    } catch (DateTimeParseException e) {
      // if can't parse to ZoneDateTime
      LocalDateTime dateTime  = LocalDateTime.parse(dateTimeValue, dateTimeFormatter);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...