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

Работа с датами в js-joda строится на принципе строгой типизации и неизменяемости объектов времени. Это означает, что некорректные значения не приводят к «полурабочим» объектам — библиотека либо возвращает валидный экземпляр даты/времени, либо завершает выполнение с ошибкой. Такая модель делает проверку корректности ключевым этапом при обработке входных данных.


Строгая модель корректности данных времени

В js-joda корректной считается дата или время, которые:

  • соответствуют календарным ограничениям (например, не существует 31 февраля)
  • укладываются в диапазоны полей (месяц от 1 до 12, день от 1 до 31 с учётом месяца)
  • удовлетворяют правилам конкретного календаря (григорианский календарь)
  • корректно интерпретируются при разборе строки

Любое нарушение этих условий приводит к исключению, а не к частично созданному объекту.


Разбор строк и проверка формата

Основной способ получения даты из внешнего ввода — парсинг строк:

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

const date = LocalDate.parse('2026-05-25');

Если строка не соответствует формату ISO или содержит недопустимые значения, возникает ошибка:

LocalDate.parse('2026-02-30'); // ошибка
LocalDate.parse('2026-13-10'); // ошибка

Тип ошибки — DateTimeParseException или DateTimeException (в зависимости от контекста и версии сборки).


Контроль ошибок через исключения

Проверка корректности часто строится на перехвате исключений:

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

function isValidDate(input) {
  try {
    LocalDate.parse(input);
    return true;
  } catch (e) {
    return false;
  }
}

Такой подход используется при обработке пользовательского ввода, где формат заранее неизвестен.


Конструирование даты через of и контроль диапазонов

Метод of создаёт дату напрямую из компонентов:

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

const date = LocalDate.of(2026, 5, 25);

При передаче некорректных значений происходит немедленная ошибка:

LocalDate.of(2026, 2, 30); // ошибка
LocalDate.of(2026, 0, 10);  // ошибка
LocalDate.of(2026, 13, 1);  // ошибка

Это позволяет выявлять ошибки ещё до появления строкового представления.


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

Для более тонкой валидации используются ограничения диапазонов:

  • месяц: 1–12
  • день: зависит от месяца и года
  • год: в js-joda не ограничен искусственно, но может ограничиваться бизнес-логикой

Пример ручной проверки перед созданием даты:

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

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

Учёт високосных лет

Корректность даты зависит от високосных правил:

  • 29 февраля существует только в високосный год
  • 2024, 2028 — допустимы
  • 2023, 2025 — недопустимы
LocalDate.of(2024, 2, 29); // корректно
LocalDate.of(2023, 2, 29); // ошибка

Проверка високосного года встроена в календарную систему js-joda и не требует дополнительной логики.


Использование форматтеров и строгого разбора

При работе с нестандартными форматами применяется DateTimeFormatter:

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

const formatter = DateTimeFormatter.ofPattern('dd/MM/yyyy');

const date = LocalDate.parse('25/05/2026', formatter);

Строгая проверка формата означает:

  • несоответствие шаблону приводит к ошибке
  • перестановка полей (например, месяц вместо дня) не исправляется автоматически

Ленивый и строгий разбор

В js-joda используется строгая модель интерпретации входных данных. При разборе:

  • 25/13/2026 не будет «исправлено» на 25 декабря
  • 32/01/2026 всегда ошибка
  • отсутствует автоматическая нормализация

Это снижает риск скрытых ошибок в данных.


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

Некоторые типы времени поддерживают не все поля. Например:

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

const date = LocalDate.now();

date.isSupported('NANO_OF_DAY'); // false
date.isSupported('YEAR');        // true

Метод isSupported позволяет заранее определить применимость операций к объекту времени.


Валидация диапазонов времени через ChronoField

Для проверки значений используются поля из ChronoField:

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

const date = LocalDate.of(2026, 5, 25);

date.get(ChronoField.DAY_OF_MONTH); // 25

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

function validateDay(day) {
  return day >= 1 && day <= 31;
}

Проверка Instant и эпохи времени

При работе с Instant корректность связана с диапазоном эпохи:

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

const instant = Instant.ofEpochSecond(0);

Некорректные значения (например, выходящие за допустимые пределы представления) приводят к исключениям.


Валидация часовых зон

При использовании ZonedDateTime корректность включает проверку зоны:

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

const zone = ZoneId.of('Europe/Moscow');
const dateTime = ZonedDateTime.now(zone);

Некорректные идентификаторы зон вызывают ошибку:

ZoneId.of('Invalid/Zone'); // ошибка

Проверка логических ограничений (бизнес-правила)

Корректность даты часто определяется не только календарём, но и логикой предметной области:

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

Пример проверки возраста:

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

function isAdult(birthDateStr) {
  const birthDate = LocalDate.parse(birthDateStr);
  const today = LocalDate.now();

  return birthDate.plusYears(18).isBefore(today)
      || birthDate.plusYears(18).isEqual(today);
}

Защита от некорректного пользовательского ввода

Типовой поток проверки:

  1. попытка парсинга
  2. перехват исключений
  3. дополнительная логическая проверка
  4. возврат валидного результата или отказ
function parseDateOrNull(input) {
  try {
    const date = LocalDate.parse(input);

    if (date.getYear() < 1900) return null;

    return date;
  } catch {
    return null;
  }
}

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

Корректность может определяться через сравнение:

const start = LocalDate.parse('2026-01-01');
const end = LocalDate.parse('2026-12-31');

const current = LocalDate.now();

const valid = !current.isBefore(start) && !current.isAfter(end);

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


Комбинированные стратегии проверки

На практике проверка корректности включает несколько уровней:

  • синтаксический (формат строки)
  • календарный (существование даты)
  • типовой (поддержка полей)
  • семантический (бизнес-правила)

Пример комплексной функции:

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

function validate(input) {
  try {
    const date = LocalDate.parse(input);

    if (date.getYear() < 2000) return false;
    if (date.isAfter(LocalDate.now().plusYears(10))) return false;

    return true;
  } catch {
    return false;
  }
}

Особенности обработки некорректных данных

Ключевая особенность js-joda заключается в том, что:

  • некорректные значения не преобразуются автоматически
  • отсутствует «мягкое исправление» дат
  • каждая ошибка фиксируется явно
  • корректность проверяется на этапе создания объекта

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