Разбор даты с шаблоном 'dd MMMMM uuuu' с использованием DateTimeFormatter - PullRequest
1 голос
/ 08 марта 2019

Почему этот код дает мне исключение?

String myFormat = "dd MMMMM uuuu";
String dateToFormat = "26 Mai 2010";
DateTimeFormatter myFormatter = new DateTimeFormatterBuilder().appendPattern(myFormat)
            .toFormatter().withResolverStyle(ResolverStyle.STRICT);
LocalDate myDate=LocalDate.parse(dateToFormat,myFormatter);

Исключение:

java.time.format.DateTimeParseException: Text '26 Mai 2010' could not be parsed at index 4
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
    at java.time.LocalDate.parse(LocalDate.java:400)

Если я попытаюсь использовать «ММММ» вместо «МММММ», он будет работать, как и ожидалось.

String myFormat = "dd MMMM uuuu";

1 Ответ

5 голосов
/ 08 марта 2019

Как объясняет javadoc DateTimeFormatter, и я цитирую: Ровно 4 буквы шаблона будут использовать полную форму.Точно 5 шаблонных букв будут использовать узкую форму.

Я тоже не знаю почему;узкие формы на самом деле очень и очень короткие, предположительно, месяцами это будет первая буква, что крайне бесполезно, например, июнь и июль начинаются с буквы J (даже на немецком языке).Самый простой способ разобраться в подобных вещах - это пойти наоборот: возьмите известную дату и используйте .format вместо .parse, чтобы посмотреть, как она выглядит.

То, что вам нужно, - это 4-кратная букваM, которое является полным названием месяца.

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

Вот пример кода, с которым можно поиграть:

import java.time.*; import java.time.format.*; import java.util.*;

public class Test {
    public static void main(String[] args) {
        String myFormatNarrow = "dd MMMMM uuuu";
        String myFormatFull = "dd MMMM uuuu";
        String dateToFormat = "26 Juni 2010";
        String dateToFormat2 = "26 J 2010";
        String dateToFormat3 = "26 Jun 2010";
        DateTimeFormatter myFormatter;
        LocalDate myDate;
        myFormatter = new DateTimeFormatterBuilder().appendPattern(myFormatFull)
                    .toFormatter().withResolverStyle(ResolverStyle.STRICT).withLocale(Locale.GERMAN);
        System.out.println("FULL: " + myFormatter.format(LocalDate.of(2010, 6, 26)));
        myDate = LocalDate.parse(dateToFormat, myFormatter);
        System.out.println("PARSED: " + myDate);
        myFormatter = new DateTimeFormatterBuilder().appendPattern(myFormatNarrow)
                    .toFormatter().withResolverStyle(ResolverStyle.STRICT).withLocale(Locale.GERMAN);
        System.out.println("NARROW: " + myFormatter.format(LocalDate.of(2010, 6, 26)));
        myDate = LocalDate.parse(dateToFormat2, myFormatter);
        // It parses a single J as 'july'. Clearly showing why narrow-form is useless here.
        System.out.println("PARSED: " + myDate);
        // note that even ResolverStyle.LENIENT can't do it either; this will fail:
        myFormatter = myFormatter.withResolverStyle(ResolverStyle.LENIENT);
    //   myDate = LocalDate.parse(dateToFormat3, myFormatter);
    // System.out.println("PARSED: " + myDate);
    }
}
...