Java 8 DateTimeFormatter отклоняет правильную дату / время ISO 8601 со смещением - PullRequest
0 голосов
/ 05 февраля 2019

Я использую строку формата для DateTimeFormatter: uuuu-MM-dd'T'HH: mm: ssX

, которая должна поддерживать все возможные форматы смещения часового пояса, включая: Z, 00, 00:00, 0000

Согласно официальной документации DateTimeFormatter, квалификатор 'X' должен совпадать со смещением в следующих форматах:

X-смещение зоны 'Z' для нулевого смещения-X Z;-08;-0830;-08: 30;-083015;-08: 30: 15;

но на самом деле это не

строка ввода : "2014-01-01T00: 30: 00+00:00 "

результат : java.time.format.DateTimeParseException: текст '2014-01-01T00: 30: 00 + 00: 00' не может быть проанализирован,необработанный текст найден в индексе 22 * ​​1020 *

строка ввода : "2014-01-01T00: 30: 00Z"

результат : правильный

код:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssX");
OffsetDateTime parsed = OffsetDateTime.parse(dateTimeAsString, formatter);

JDK 1.8.0_192 (Oracle, не OpenJDK)

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019

Не жестко кодировать любой формат даты ISO.DateFormatter уже имеет статический метод для преобразования формата даты ISO.Используйте следующий код:

DateTimeFormatter formatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;

OffsetDateTime parsed = OffsetDateTime.parse (dateTimeAsString, formatter);

1007 * * 1008работать наверняка.Пожалуйста, найдите эту ссылку для получения дополнительных опций форматирования.

0 голосов
/ 05 февраля 2019

Это немного сложно. Как говорит jvdmr , количество X имеет значение.XXXXX распознает -08:30:15, но не -083015.XXXX распознает последний, но не первый.

Чтобы принять во внимание все возможные примеры форматов, нам нужно указать различные возможности.Это можно сделать в строке шаблона формата с использованием квадратных скобок.Они включают дополнительные части.Небольшой эксперимент показал, что следующий шаблон охватывает все примеры:

uuuu-MM-dd'T'HH:mm:ss[XXXXX][XXXX][X]

Давайте попробуем:

    DateTimeFormatter formatter
            = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss[XXXXX][XXXX][X]");
    for (String dts : new String[] {
            "2014-01-01T00:30:00-08:30:15", "2014-01-01T00:30:00-083015",
            "2014-01-01T00:30:00-08:30", "2014-01-01T00:30:00-0830",
            "2014-01-01T00:30:00-08", "2014-01-01T00:30:00Z",
    }) {
        System.out.println(OffsetDateTime.parse(dts, formatter));
    }

Вывод из этогоФрагмент:

2014-01-01T00:30-08:30:15
2014-01-01T00:30-08:30:15
2014-01-01T00:30-08:30
2014-01-01T00:30-08:30
2014-01-01T00:30-08:00
2014-01-01T00:30Z

Редактировать

VelNaga предлагает не жестко кодировать форматы даты и времени ISO.Поскольку написание строк шаблона формата подвержено ошибкам, это может быть хорошей идеей.Например:

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            .appendPattern("[XXXXX][XXXX][X]")
            .toFormatter();

Вывод с использованием этого форматера такой же, как с использованием приведенного выше.Это словесно, но мы могли бы легко подумать, что оно того стоит, поскольку оно менее подвержено ошибкам и может быть более ясным и легким для чтения.

0 голосов
/ 05 февраля 2019

Из документов (выделено мной) :

Смещение X и x: Это форматирует смещение на основе количества букв образца. Одна буква выводит только час, например, «+01», если только минута не является ненулевой, в этом случае также выводится минута, например, «+0130».Две буквы выводят час и минуту без двоеточия, например «+0130». Три буквы выводят часы и минуты с двоеточием, например, «+01: 30». Четыре буквы выводят часы и минуты и необязательную секунду без двоеточия, например, «+013015».Пять букв выводят часы и минуты и необязательную секунду с двоеточием, например «+01: 30: 15».Шесть или более букв выбрасывают исключение IllegalArgumentException.Буква шаблона «X» (верхний регистр) будет выводить «Z», когда выводимое смещение будет равно нулю, а буква шаблона «x» (нижний регистр) будет выводить «+00», «+0000» или «+00».: 00 '.

Это также работает в обратном порядке при разборе дат.Вы хотите выполнить синтаксический анализ как с двоеточиями, так и без них. Это означает, что вам придется использовать дополнительные секции, поскольку ни один шаблон не поддерживает это.Попробуйте этот шаблон: "uuuu-MM-dd'T'HH:mm:ss[XXX][XXXX]"

...