DateTimeFormatter не может проанализировать строку даты, но SimpleDateFormat может - PullRequest
0 голосов
/ 07 января 2020

Я не могу разобрать эту примерную строку даты - «312015», представляющую «3 января 2015», используя метод синтаксического анализа LocalDate. Может ли кто-нибудь, пожалуйста, помогите.

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class TestDOB {

    public static void main(String[] args) throws ParseException {
        // TODO Auto-generated method stub

        String dateOfBirth = "312015";
        SimpleDateFormat sdf = new SimpleDateFormat("dMyyyy");
        System.out.println(sdf.parse(dateOfBirth)); 
        // The above outputs Sat Jan 03 00:00:00 CST 2015

        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dMyyyy").withLocale(Locale.getDefault());
        LocalDate dateTime = LocalDate.parse(dateOfBirth, dateFormatter);

        // The above parsing statement with LocalDate parse method runs into below error - 


    }

}

Error on console- 

Exception in thread "main" java.time.format.DateTimeParseException: Text '312015' could not be parsed at index 6
    at java.time.format.DateTimeFormatter.parseResolved0(Unknown Source)
    at java.time.format.DateTimeFormatter.parse(Unknown Source)
    at java.time.LocalDate.parse(Unknown Source)
    at TestDOB.main(TestDOB.java:30)

1 Ответ

3 голосов
/ 08 января 2020

DateTimeFormatterBuilder.appendValue (TemporalField, int)

Я был удивлен, обнаружив, что это возможно (это не имеет большого смысла для меня).

    DateTimeFormatter dateFormatter = new DateTimeFormatterBuilder()
            .appendValue(ChronoField.DAY_OF_MONTH, 1)
            .appendValue(ChronoField.MONTH_OF_YEAR, 1)
            .appendValue(ChronoField.YEAR, 4)
            .toFormatter();

    String dateOfBirth = "312015";
    LocalDate dateTime = LocalDate.parse(dateOfBirth, dateFormatter);
    System.out.println(dateTime);

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

2015-01-03

У него есть некоторые ограничения, которые я бы посчитал довольно серьезными: он может анализировать только даты, которые находятся в пределах дней 1 –9 месяца (не 10–31) в месяцах с января по сентябрь (не с октября по декабрь), поскольку он настаивает на том, чтобы день месяца и месяц составляли всего 1 ди git каждый.

Вы можете избавиться ограничения на день месяца , пропуская второй аргумент 1 из первого вызова appendValue(). Подобный трюк будет не работать в течение месяца, поэтому последний квартал года вне досягаемости.

Почему не сработали один d и один M?

Почему принудительное использование одного d и одного M здесь не работает? Я что-то здесь упускаю?

До DateTimeFormatter одна буква шаблона для поля цифры c означает «столько цифр, сколько нужно» (а не «1 цифра», как это могло бы быть) ожидалось). Это не очень хорошо задокументировано. В этом предложении есть подсказка из документации:

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

Что происходит, так это то, что синтаксический анализ потребляет столько цифр, сколько он может за день месяца (до внутреннего предела 19). В этом случае вся строка. Теперь он не может разобрать ни одного месяца. Это причина сообщения об ошибке:

Текст «312015» не может быть проанализирован с индексом 6

Индекс 6 - это конец строки.

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

Документация DateTimeFormatter

...