Валидация дат

Корректность даты в Day.js определяется не только синтаксисом строки, но и возможностью библиотеки интерпретировать значение как валидный момент времени. Любая дата проходит стадию парсинга, после которой формируется объект Day.js. Внутри этого процесса возможны два результата: корректная дата или невалидное значение, помеченное специальным флагом.

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


Базовая проверка валидности через isValid

Основной механизм проверки корректности даты реализуется методом isValid.

import dayjs from "dayjs";

dayjs("2026-05-22").isValid(); // true
dayjs("invalid-date").isValid(); // false

Метод работает на уровне внутреннего состояния объекта. После попытки парсинга Day.js устанавливает флаг валидности, который и используется при проверке.

Важно учитывать, что Day.js не выбрасывает исключения даже при полностью некорректных данных:

const d = dayjs("not-a-date");

d.isValid(); // false
d.format();  // "Invalid Date"

Особенности парсинга входных значений

Day.js поддерживает несколько типов входных данных:

  • ISO 8601 строки
  • Unix timestamp (миллисекунды)
  • JavaScript Date
  • строковые представления дат

Примеры:

dayjs("2026-01-01");        // ISO строка
dayjs(1700000000000);       // timestamp
dayjs(new Date());          // объект Date

При этом поведение при некорректных строках отличается от строгих парсеров. Без дополнительных плагинов Day.js использует упрощённую стратегию интерпретации, что может приводить к неожиданным результатам:

dayjs("2026-99-99").isValid(); // false
dayjs("2026-13-01").isValid(); // false или корректировка в зависимости от парсинга

Невалидные даты и их поведение

Невалидный объект Day.js не прерывает цепочку вызовов. Любая операция продолжает выполняться, но результат остаётся невалидным.

const d = dayjs("wrong input")
  .add(1, "day")
  .subtract(2, "year");

d.isValid(); // false

Форматирование такой даты возвращает стандартную строку:

d.format(); // "Invalid Date"

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


Строгий разбор форматов с customParseFormat

Для задач валидации пользовательского ввода применяется плагин customParseFormat. Он позволяет задавать точную маску входной строки и исключать неоднозначный парсинг.

Подключение плагина:

import dayjs from "dayjs";
import customParseFormat from "dayjs/plugin/customParseFormat";

dayjs.extend(customParseFormat);

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

dayjs("22/05/2026", "DD/MM/YYYY", true).isValid(); // true
dayjs("2026/22/05", "DD/MM/YYYY", true).isValid(); // false

Третий параметр true включает строгий режим. В этом режиме:

  • порядок компонентов фиксирован
  • лишние символы запрещены
  • частичные совпадения исключаются

Валидация пользовательского ввода

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

Пример базовой схемы:

const input = "31/02/2026";

const date = dayjs(input, "DD/MM/YYYY", true);

const isCorrect = date.isValid();

Однако одной проверки формата недостаточно. Некорректные календарные даты, такие как 31 февраля, также могут проходить синтаксическую проверку формата, но будут отклонены на уровне календарной логики:

dayjs("31/02/2026", "DD/MM/YYYY", true).isValid(); // false

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

Валидация часто включает проверку попадания даты в допустимый интервал.

const date = dayjs("2026-05-22");

const min = dayjs("2020-01-01");
const max = dayjs("2030-01-01");

const inRange =
  date.isValid() &&
  date.isAfter(min) &&
  date.isBefore(max);

Методы isAfter и isBefore работают только с валидными объектами. При невалидной дате результат всегда будет ложным, поэтому первичная проверка обязательна.


Работа с Unix timestamp и ошибки интерпретации

Unix timestamp часто используется в API, однако ошибка единиц измерения приводит к некорректной интерпретации:

dayjs(1700000000).isValid(); // интерпретация как миллисекунды → неверная дата
dayjs(1700000000000).isValid(); // корректный timestamp

Валидация timestamp обычно требует дополнительного контроля диапазона значений:

const ts = 1700000000000;

const isValidTs =
  typeof ts === "number" &&
  ts > 0 &&
  dayjs(ts).isValid();

Проверка ISO 8601 и неоднозначных строк

ISO 8601 является наиболее надёжным форматом для Day.js. Однако частичные или расширенные строки могут вызывать неоднозначность.

dayjs("2026-05-22T10:20:30Z").isValid(); // true
dayjs("2026-05-22 10:20:30").isValid();  // зависит от парсера

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


Типичные ошибки валидации

Отсутствие проверки isValid

const d = dayjs("invalid");
console.log(d.format("YYYY-MM-DD")); // "Invalid Date"

Игнорирование проверки приводит к распространению невалидного состояния по цепочке вычислений.


Доверие нестрогому парсингу

dayjs("2026-13-40").isValid();

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


Смешивание форматов

dayjs("22-05-2026"); // неоднозначный формат
dayjs("05-22-2026"); // интерпретация зависит от окружения

Без явного формата результат становится нестабильным.


Комплексные схемы валидации

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

import dayjs from "dayjs";
import customParseFormat from "dayjs/plugin/customParseFormat";

dayjs.extend(customParseFormat);

function validateDate(input) {
  const d = dayjs(input, "DD/MM/YYYY", true);

  if (!d.isValid()) return false;

  if (d.year() < 1900) return false;

  if (d.year() > 2100) return false;

  return true;
}

Такая схема объединяет:

  • синтаксическую проверку
  • календарную корректность
  • ограничение бизнес-логикой

Поведение при цепочках преобразований

Невалидная дата сохраняет состояние на всех этапах цепочки:

const result = dayjs("bad-input")
  .add(5, "day")
  .set("year", 2026);

result.isValid(); // false

Любые операции не «исправляют» исходную ошибку, а лишь распространяют её.


Проверка даты без создания побочных эффектов

Иногда требуется валидация без последующих преобразований:

const isDateValid = (value) => dayjs(value).isValid();

Для строгих форматов:

const isStrictDateValid = (value) =>
  dayjs(value, "YYYY-MM-DD", true).isValid();

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