Проверка валидности дат

Валидация дат в js-joda строится на строгой модели календарно-временных типов, где любая некорректная комбинация значений приводит к немедленному исключению. Библиотека ориентирована на предсказуемое поведение и исключает «тихие» преобразования невалидных дат.

Строгая модель допустимых значений

Все классы js-joda (LocalDate, LocalTime, LocalDateTime, ZonedDateTime) используют проверку допустимости значений на этапе создания объекта. Это означает, что невозможные даты не могут существовать в состоянии объекта.

Пример жёсткой валидации:

import { LocalDate } from '@js-joda/core';

const date = LocalDate.of(2023, 2, 30);

В данном случае произойдёт выброс исключения DateTimeException, поскольку 30 февраля не существует в григорианском календаре. Таким образом, проверка валидности встроена в конструкторную логику.


Валидация при разборе строк

При парсинге строкового представления дат используется форматтер ISO по умолчанию. Некорректные строки приводят к исключению DateTimeParseException.

import { LocalDate } from '@js-joda/core';

const date = LocalDate.parse('2024-13-01');

Здесь значение месяца выходит за допустимый диапазон (1–12), что делает строку невалидной.

Проверка валидности в этом случае осуществляется автоматически на этапе парсинга без необходимости дополнительных условий.


Проверка через исключения как основной механизм

В js-joda отсутствует универсальный метод вида isValidDate(), поскольку модель библиотеки предполагает отказ от «предположительной» валидации. Вместо этого используется стратегия «fail-fast» — любая ошибка выявляется немедленно через исключение.

Типичные источники невалидности:

  • некорректный день месяца (31 апреля, 30 февраля)
  • выход за пределы допустимых значений месяца (0 или 13)
  • отрицательные значения, не поддерживаемые типом
  • несоответствие формата строки при парсинге

Пример обработки:

import { LocalDate } from '@js-joda/core';

function safeParse(dateString) {
  try {
    return LocalDate.parse(dateString);
  } catch (e) {
    return null;
  }
}

Такой подход переносит ответственность за проверку на уровень обработки исключений.


Проверка через предварительное разложение значений

Перед созданием объекта возможно ручное определение корректности компонентов даты:

function isValidDate(year, month, day) {
  try {
    LocalDate.of(year, month, day);
    return true;
  } catch (e) {
    return false;
  }
}

Данный механизм фактически использует саму библиотеку как источник истины о корректности календаря.


Контроль диапазонов значений

Некоторые проверки можно выполнить без создания объекта, используя знание допустимых диапазонов:

  • месяц: 1–12
  • день: 1–28/29/30/31 (в зависимости от месяца и года)
  • год: не ограничен жёстко, но зависит от используемого типа и контекста

Однако ручная проверка диапазонов не заменяет полноценную валидацию, поскольку правила календаря включают сложные зависимости (например, високосные годы).


Високосные годы и календарная корректность

Корректность дат зависит от правил григорианского календаря. js-joda автоматически учитывает високосные годы.

LocalDate.of(2024, 2, 29); // корректно
LocalDate.of(2023, 2, 29); // исключение

Проверка валидности таким образом включает не только синтаксическую корректность, но и календарную семантику.


Валидация при работе с временными зонами

Для ZonedDateTime и OffsetDateTime добавляется дополнительный слой проверки — корректность смещения и существование локального времени в зоне.

import { ZonedDateTime, ZoneId } from '@js-joda/core';

const zdt = ZonedDateTime.of(
  2024, 3, 31, 2, 30, 0, 0,
  ZoneId.of('Europe/Berlin')
);

В некоторых зонах возможны «дырки» во времени (например, переход на летнее время), что может привести к корректировке или исключению в зависимости от сценария.


Проверка поддерживаемости полей времени

Для более низкоуровневой валидации используется метод isSupported, который позволяет определить, применимо ли поле к конкретному типу времени:

import { ChronoField, LocalDate } from '@js-joda/core';

const date = LocalDate.now();

date.isSupported(ChronoField.HOUR_OF_DAY); // false

Это не проверка валидности даты как таковой, но механизм контроля допустимых операций над временными сущностями.


Типовые стратегии валидации в прикладном коде

В реальных сценариях применяется комбинация подходов:

  • создание объекта через of или parse с перехватом исключений
  • проверка строкового формата до парсинга (регулярные выражения)
  • проверка диапазонов чисел на уровне UI или API
  • централизованная обработка ошибок временных типов

Пример комбинированной проверки:

import { LocalDate } from '@js-joda/core';

function validateDateInput(year, month, day) {
  if (month < 1 || month > 12) return false;
  if (day < 1 || day > 31) return false;

  try {
    LocalDate.of(year, month, day);
    return true;
  } catch {
    return false;
  }
}

Особенности отсутствия «мягкой» валидации

Архитектура js-joda исключает сценарии, в которых объект даты может находиться в невалидном состоянии. Это приводит к следующим характеристикам:

  • невозможность создания «частично корректной» даты
  • отсутствие nullable-временных состояний внутри объекта
  • обязательная проверка корректности при конструировании
  • предсказуемость всех операций над датами

Такой подход делает проверку валидности не отдельной функцией, а встроенным свойством всей модели данных.