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

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

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


Метод проверки валидности: isValid()

Основной инструмент проверки:

dayjs(date).isValid()

Метод возвращает:

  • true — дата корректно распознана и может использоваться в вычислениях
  • false — результат парсинга некорректен или дата не существует

Примеры:

import dayjs from 'dayjs'

dayjs('2024-05-20').isValid() // true
dayjs('invalid-date').isValid() // false
dayjs(null).isValid()          // false
dayjs(undefined).isValid()     // false

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


Внутреннее поведение невалидных дат

При создании некорректной даты:

const d = dayjs('not-a-date')

библиотека:

  • создаёт объект Day.js
  • помечает его внутренним флагом валидности как false
  • возвращает строковое представление "Invalid Date" при форматировании

Пример:

const d = dayjs('not-a-date')

d.format('YYYY-MM-DD') // "Invalid Date"
d.toString()           // "Invalid Date"
d.isValid()            // false

Таким образом, объект остаётся цепочечным, но его вычислительная ценность отсутствует.


Причины появления невалидных дат

1. Неподдерживаемый формат строки

dayjs('31-02-2024').isValid() // false

Причина — отсутствие строгого понимания формата без дополнительного парсера.


2. Некорректные значения календаря

dayjs('2024-02-30').isValid() // false
dayjs('2023-13-10').isValid() // false

Февраль не содержит 30 дней, а месяц 13 не существует.


3. Пустые и неопределённые значения

dayjs(null).isValid()      // false
dayjs(undefined).isValid() // false

Такие значения не приводятся к корректной дате.


4. Некорректные timestamp значения

dayjs(NaN).isValid() // false

Особенности парсинга и влияние формата

По умолчанию Day.js использует небуквальный (loose) парсинг, основанный на встроенном Date.

Это означает:

dayjs('2024-01-01') // обычно валидно
dayjs('2024/01/01') // зависит от окружения

Разные окружения (браузер / Node.js) могут интерпретировать строки по-разному, что делает проверку валидности критически важной.


Строгий парсинг с customParseFormat

Для детерминированной проверки используется плагин customParseFormat:

import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat'

dayjs.extend(customParseFormat)

Пример строгой проверки:

dayjs('31-12-2024', 'DD-MM-YYYY', true).isValid() // true
dayjs('31-02-2024', 'DD-MM-YYYY', true).isValid() // false

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

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

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

Любая операция над датой сохраняет флаг валидности:

const d = dayjs('invalid-date').add(1, 'day')

d.isValid() // false

Даже после арифметических операций объект остаётся невалидным, если исходная база была ошибочной.


Сравнение с нативным Date

Встроенный Date ведёт себя иначе:

new Date('invalid-date') // Invalid Date (но объект существует)

Различие:

  • Date не имеет метода isValid
  • проверка выполняется через isNaN(date.getTime())
  • поведение менее унифицировано

В Day.js проверка стандартизирована:

dayjs(date).isValid()

Практические паттерны проверки

Защитная проверка перед форматированием

const d = dayjs(input)

if (d.isValid()) {
  console.log(d.format('YYYY-MM-DD'))
}

Функция нормализации входных данных

function safeDate(value) {
  const d = dayjs(value)
  return d.isValid() ? d : null
}

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

const dates = ['2024-01-01', 'bad-date', '2024-03-10']

const validDates = dates.filter(d => dayjs(d).isValid())

Частые ошибки при проверке валидности

Проверка исходного значения вместо объекта

dayjs('invalid') ? true : false // всегда true (ошибка логики)

Любой вызов dayjs() возвращает объект, поэтому проверка без isValid() некорректна.


Игнорирование локального формата

dayjs('31/12/2024').isValid() // может быть false

Без явного формата такие строки часто интерпретируются неверно.


Смешивание timestamp и строк

dayjs('1710000000000').isValid() // может трактоваться как строка
dayjs(1710000000000).isValid()   // корректно как timestamp

Поведение при форматировании невалидных дат

dayjs('broken').format('YYYY-MM-DD') // "Invalid Date"

Любой формат возвращает строку "Invalid Date", независимо от шаблона.

Это позволяет унифицировать обработку ошибок на уровне UI и логики отображения.


Влияние плагинов на валидность

Некоторые плагины не изменяют правила валидности, но расширяют способы создания даты:

  • customParseFormat — строгий парсинг
  • utc — работа с UTC-временем
  • timezone — учёт часовых поясов

Однако итоговое правило остаётся неизменным: валидность определяется через isValid() на итоговом объекте.


Композиция проверок в цепочках

const result = dayjs(input)
  .add(2, 'day')
  .subtract(1, 'month')

if (result.isValid()) {
  // безопасное использование
}

Цепочки операций не требуют промежуточных проверок, если исходное значение уже гарантированно валидно.