Локальный анализ даты не работает без разделителей - PullRequest
0 голосов
/ 04 февраля 2019

У меня дата отформатирована следующим образом:

Год из четырех цифр, а затем номер недели из двух цифр.

Например, четвертая неделяиз 2018 будет 201804 .

У меня возникли проблемы с анализом этих дат с использованием LocalDate и DateTimeFormatterBuilder .

* 1016.* Вот как я пытаюсь разобрать дату:
LocalDate.parse(
    "201804",
    new DateTimeFormatterBuilder().appendPattern("YYYYww").parseDefaulting(WeekFields.ISO.dayOfWeek(), 1).toFormatter()
);

При выполнении выдается следующее исключение:

java.time.format.DateTimeParseException: текст «201804» не можетбыть проанализирован по индексу 0

Странное поведение заключается в том, что, когда я добавляю разделитель между частями даты, исключение больше не генерируется:

LocalDate.parse(
    "2018 04",
    new DateTimeFormatterBuilder().appendPattern("YYYY ww").parseDefaulting(WeekFields.ISO.dayOfWeek(), 1).toFormatter()
);

Результат:

2018-01-22

Есть что-то, чего мне не хватает в форматере?

Ответы [ 4 ]

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

Вы можете использовать appendValue

Этот метод поддерживает специальную технику синтаксического анализа, известную как «анализ смежных значений».Этот метод решает проблему, когда за значением, переменной или фиксированной шириной, следует одно или несколько значений фиксированной длины.Стандартный синтаксический анализатор является жадным, и, таким образом, он обычно крал бы цифры, которые нужны анализаторам фиксированной ширины, которые следуют за переменной шириной один.

Никаких действий не требуется для запуска «анализа соседних значений».Когда выполняется вызов appendValue, компоновщик переходит в режим настройки парсинга смежных значений.

Так что это работает:

LocalDate.parse(
                "201804",
                new DateTimeFormatterBuilder()
                        .appendValue(YEAR, 4)
                        .appendValue(ALIGNED_WEEK_OF_YEAR, 2)
                        .parseDefaulting(WeekFields.ISO.dayOfWeek(), 1).toFormatter()
        );
0 голосов
/ 04 февраля 2019

Попробуйте явно определить хронополя:

DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
DateTimeFormatter formatter = 
      builder.appendValue(ChronoField.YEAR, 4)
             .appendValue(ChronoField.ALIGNED_WEEK_OF_YEAR, 2)
             .parseDefaulting(ChronoField.DAY_OF_WEEK, 1)
             .toFormatter();

LocalDate.parse("201804", formatter);
0 голосов
/ 04 февраля 2019

Да, это также убило меня много раз из-за данных из иностранных источников ....

В зависимости от того, что вы получаете, вам нужны разные парсеры.Для даты вам нужен LocalDate, а для чего-то со временем вам нужен LocalTimedate.parse.

Значение, если вы не знаете, какие данные вы получаете (обычно текущий день без даты, но со временем, а с другой стороны, даты в прошлом без времени, но с датой - так что вы не знаете)Вы должны сначала выполнить грубый анализ самостоятельно, чтобы определить конкретный формат, и только после этого Java разрешает его анализировать .... Обработка даты в Javas imho немного сложна.

Итак, решение таково: использовать LocalDateвместо LocalTimeDate.

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

Разве это не просто выполнение этой работы?

LocalDate.parse("2018041", DateTimeFormatter.ofPattern("YYYYwwe"));

По сути, вам нужно сказать, что вы хотите указать дату Monday этой недели, а не только недели.

...