java .time.format.DateTimeParseException при разборе года - PullRequest
4 голосов
/ 03 февраля 2020

Используется jdk: 1.8

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

public class Test {

    public static void main(String[] args) {
        String configuredFormat = "yyyyMMddHHmmssSSS";
        String inputTime = "20200203164553123";

        DateTimeFormatter dt = DateTimeFormatter.ofPattern(configuredFormat);
        DateTimeFormatter strictTimeFormatter = dt.withResolverStyle(ResolverStyle.STRICT);
        try {
            LocalTime.parse(inputTime, strictTimeFormatter);
            System.out.println("success");
        } catch (DateTimeParseException | NullPointerException e) {
            e.printStackTrace();
        }
    }
}

Исключение, которое я получаю:

java.time.format.DateTimeParseException: Text '20200203164553123' could not be parsed at index 0
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
    at java.time.LocalTime.parse(LocalTime.java:441)
    at com.Test.main(Test.java:20)

Ответы [ 2 ]

9 голосов
/ 03 февраля 2020

К счастью для вас, есть отчет об ошибке точный , который использует тот же шаблон, что и вы. Кто лучше объяснит, чем сопровождающие JDK?

JDK-8031085

Обходной путь

DateTimeFormatter dtf = new
DateTimeFormatterBuilder()
    .appendPattern("yyyyMMddHHmmss")
    .appendValue(ChronoField.MILLI_OF_SECOND,3)
    .toFormatter()

Синтаксический анализ соседних значений обычно труден проблема. Он предназначен для обработки случая, когда первый элемент имеет переменную ширину (год), а все остальные элементы имеют фиксированную ширину (месяц, день и т. Д. c). Однако буква «S» - это дробная часть, а не значение. В частности, дробь может быть переменной ширины - более или менее трех цифр являются возможными вариантами. Учитывая общий случай переменной ширины года и переменной ширины миллисекунды, невозможно определить, какое из двух полей было предназначено для переменной.

Сказав это, реализация (и javado c ) не закончились, как я хотел. Описание «дроби» в DateTimeFormatter описывает действия в строгом и мягком режиме, но нет доступа к строгому или мягкому режиму при использовании DateTimeFormatter.ofPattern (). Это ошибка документации, которая должна быть исправлена ​​путем удаления обсуждения строгого и снисходительного характера.

Хуже того, однако, что шаблон SSS, следовательно, в конечном итоге использовал строгий режим, когда подходящий режим будет подходящим. В настоящее время DateTimeFormatter.ofPattern ("hhmmss.SSS") требует трех цифр для миллисекунд, когда изначально предполагалось, что для этого требуется от 0 до 9 (мягкое поведение).

Я попытался изменить все DateTimeFormatter.ofPattern () метод, чтобы использовать мягкий анализ, и он не сломал тесты (что по-своему плохо). Это может быть допустимым исправлением, но только если оно включено в JDK 8, поскольку, когда люди адаптируются к строгому анализу, будет трудно сделать его снисходительным.

Учитывая, что текущая реализация требует три цифры для SSS, это поэтому очень удивительно, что разбор смежных значений не применяется.

4 голосов
/ 03 февраля 2020

На самом деле я согласен, что формат должен быть действительным ... это, кажется, подтверждается, так как я пытался использовать как oracle java 8, так и время выполнения 9, а с java 9 этого не происходит. (Я тоже пробовал IBM jre 8, и она тоже работает)

        System.out.println( System.getProperty( "java.vendor" )+" - "+System.getProperty( "java.version" ) );
        String configuredFormat = "yyyyMMddHHmmssSSS";
        String inputTime = "20200203164553123";
        DateTimeFormatter dt = DateTimeFormatter.ofPattern(configuredFormat);
        DateTimeFormatter strictTimeFormatter = dt.withResolverStyle(ResolverStyle.STRICT);
        try {
            //System.out.println( dt.parse( inputTime ) );
            LocalTime.parse(inputTime, strictTimeFormatter);
            System.out.println("success");
        } catch (DateTimeParseException | NullPointerException e) {
            e.printStackTrace();
        }

Вывод

Oracle Corporation - 9.0.4
success


IBM Corporation - 1.8.0_211
success

Oracle Corporation - 1.8.0_172
java.time.format.DateTimeParseException: Text '20200203164553123' could not be parsed at index 0
    at java.time.format.DateTimeFormatter.parseResolved0(Unknown Source)
    at java.time.format.DateTimeFormatter.parse(Unknown Source)
    at java.time.LocalTime.parse(Unknown Source)
    at test.Test2.main(Test2.java:19)
...