Анализ даты ISO 8601 в Java8, когда все поля (включая разделители, но не включая годы) являются необязательными - PullRequest
0 голосов
/ 15 октября 2018

У меня есть требование для разбора строк в формате ISO8601 в Java с различными уровнями точности.Вот несколько примеров строки, которую мне нужно проанализировать:

  • 2018
  • 2018-10
  • 2018-10-15
  • 2018-10-15T12: 00
  • 2018-10-15T12: 00: 30
  • 2018-10-15T12: 00: 30.123
  • 20181015
  • 201810151200
  • 20181015120030
  • 20181015120030.123
  • 20181015T12: 00: 30.123

Если у меня нет поля, тогда я могу принять наименьшее допустимое значениеэто применимо (например, если месяц отсутствует, я могу предположить январь, если день отсутствует, то предположить первое число месяца, а если время отсутствует, предположить полночь)

Я искал SO и всевсе примеры, которые я нашел, предполагают, что я знаю точный формат заранее.

Ответы [ 4 ]

0 голосов
/ 15 октября 2018

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

DateTimeFormatter dtf = new DateTimeFormatterBuilder()
        .appendValue(ChronoField.YEAR, 4)
        .appendPattern("[['-']MM[['-']dd[['T']HH[[':']mm[[':']ss['.'SSS]]]]]]")
        .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
        .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
        .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
        .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
        .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
        .parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
        .toFormatter();

String[] s = {
        "2018",
        "2018-10",
        "2018-10-15",
        "2018-10-15T12:00",
        "2018-10-15T12:00:30",
        "2018-10-15T12:00:30.123",
        "20181015",
        "201810151200",
        "20181015120030",
        "20181015120030.123",
        "20181015T12:00:30.123"
};
for (String line : s) {
  System.out.println(LocalDateTime.parse(line, dtf));
}

Проблема в том, что yyyy создает ValueParser(minWidth=4, maxWidth=19, SignStyle.PAD_EXEEDS), который в качестве примера анализирует дату 20181015 как year=20181015.Таким образом, мы должны ограничить ширину цифры от year до 4.

Документация гласит:

Год : Количество букв определяет минимальное полеширина, ниже которой используется отступ.

Но не указывается максимальная ширина.

0 голосов
/ 15 октября 2018

Вы можете создать DateTimeFormatter с помощью DateTimeFormatterBuilder, у которого есть метод с именем parseDefaulting().parseDefaulting() может установить значение по умолчанию, если нет соответствия.

0 голосов
/ 15 октября 2018

Для первых случаев с разделителями (-, :) можно использовать:

    DateTimeFormatter dtf = DateTimeFormatter
        .ofPattern("uuuu[-MM[-dd[['T']HH[:]mm[[:]ss[[.]SSS]]]]]");
    ParsePosition pos = new ParsePosition(0);
    TemporalAccessor result = dtf.parse(text, pos);

Однако ни uuuuMMdd, ни [-], ни ['-'] не работают для меня в Java 8.

0 голосов
/ 15 октября 2018

создать таблицу поиска DateFormatters или чего-либо еще, что вы используете, основываясь на длине входной строки и вхождении 'T'

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...