Как строго проверить дату через LocalDate.parse в Java

Как строго проверить дату через LocalDate.parse в Java
Содержание статьи

Проверка строки даты должна ответить на два разных вопроса: существует ли такой день и разрешён ли он правилами приложения. На Mentoring.digital начнём с первого: примем 29.02.2024 и отклоним 29.02.2025 без исправления исходного значения.

Выберите формат и строгий режим

LocalDate хранит календарную дату без времени и часового пояса. Для формата dd.MM.uuuu нужен свой DateTimeFormatter. У форматтера, созданного через ofPattern(), режим разрешения полей по умолчанию SMART. При проверке пользовательского ввода задайте STRICT явно.

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter format = DateTimeFormatter
                .ofPattern("dd.MM.uuuu")
                .withResolverStyle(ResolverStyle.STRICT);

        for (String input : new String[] {
                "29.02.2024", "29.02.2025", "31.04.2026"}) {
            try {
                LocalDate date = LocalDate.parse(input, format);
                System.out.println(date);
            } catch (DateTimeParseException error) {
                System.out.println("Invalid date: " + input);
            }
        }
    }
}

Ожидаются строки 2024-02-29, Invalid date: 29.02.2025 и Invalid date: 31.04.2026. Для уже заданного формата ISO, например 2026-11-12, можно использовать обычный LocalDate.parse(input): его стандартный ISO-форматтер проверяет дату строго.

Почему в шаблоне uuuu, а не yyyy

В системе шаблонов u обозначает год, а y год эры. Для простого строгого разбора даты без отдельного обозначения эры используйте uuuu. Иначе сочетание полей может не разрешиться в LocalDate, хотя написанная дата выглядит обычной.

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

Правило приложения проверяется после разбора

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

LocalDate date = LocalDate.parse("2026-11-12");
LocalDate firstAllowed = LocalDate.of(2026, 1, 1);
if (date.isBefore(firstAllowed)) {
    throw new IllegalArgumentException("Date before allowed period");
}

Здесь граница является условием примера, а не текущей датой компьютера. Если правило зависит от «сегодня», отдельно выберите часовой пояс и источник времени. Сам LocalDate не превращает календарный день в конкретный момент времени.

Проверки, которые стоит сохранить

Возьмите високосный и невисокосный февраль, 31 апреля, пустую строку и другой разделитель. Решите заранее, допустимы ли пробелы вокруг даты: если вы вызываете trim(), это отдельное правило нормализации. Не заменяйте неудачный разбор сегодняшней датой, иначе ошибка ввода станет незаметной.

Такие условия удобно разобрать на занятиях по Java Core. При работе с датами существующего приложения ментору по Java полезно показать формат API и ограничения предметной области.

Похожие статьи по данной теме