Работа с некорректными данными

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

При создании экземпляра:

dayjs('не дата')
dayjs(undefined)
dayjs(null)
dayjs({})

результатом становится объект с внутренним флагом невалидности. В отличие от стандартного Date, библиотека не пытается «исправить» входные данные эвристиками, если не подключены дополнительные плагины.


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

Любая операция над невалидным объектом сохраняет его невалидное состояние.

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

d.add(1, 'day');        // invalid
d.format('YYYY-MM-DD'); // "Invalid Date"
d.diff(dayjs());        // NaN

Ключевой принцип: ошибка не маскируется и не преобразуется в текущую дату. Это важно для предотвращения скрытых дефектов в данных.


Проверка валидности через isValid()

Основной инструмент диагностики — метод проверки состояния:

dayjs('2024-01-01').isValid(); // true
dayjs('bad input').isValid();   // false

isValid() работает на основе внутреннего флага парсинга и не выполняет повторный разбор строки. Это делает его дешёвым по производительности и безопасным для массовой проверки данных, например при обработке API-ответов.


Распространённые источники некорректных данных

Некорректные значения чаще всего возникают на границах системы:

  1. API-ответы с неполными данными

    { "date": "" }
    { "date": null }
    { "date": "0000-00-00" }
  2. Пользовательский ввод

    • произвольные строки
    • локализованные форматы
    • частично заполненные поля
  3. JSON-десериализация

    • потеря типов при сериализации
    • строки вместо дат
  4. Базы данных

    • значения-заглушки
    • устаревшие форматы
    • NULL-поля

Стратегия первичной фильтрации

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

function parseDate(input) {
  if (!input || typeof input !== 'string') return null;

  const d = dayjs(input);
  return d.isValid() ? d : null;
}

Такой подход позволяет отделить слой валидации от бизнес-логики и не распространять invalid-объекты дальше по цепочке вычислений.


Поведение форматирования при ошибках

Метод format() при невалидной дате возвращает фиксированное значение:

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

Это поведение нельзя переопределить через форматную строку. Поэтому при выводе данных требуется предварительная проверка валидности:

const d = dayjs(value);

const output = d.isValid()
  ? d.format('YYYY-MM-DD')
  : '';

Пропагация невалидного состояния в цепочках

Любая цепочка методов наследует состояние исходного объекта:

const result = dayjs('bad')
  .add(5, 'day')
  .subtract(1, 'month')
  .format();

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


Работа с числовыми значениями и NaN

Некорректные числовые входы также приводят к invalid-состоянию:

dayjs(NaN).isValid(); // false
dayjs(0/0).isValid(); // false

При этом числовые таймстемпы интерпретируются строго:

dayjs(1690000000000).isValid(); // true

Ошибки часто возникают при неявном приведении типов:

dayjs("1690000000000") // строка может быть корректно распознана

Но поведение зависит от формата и настроек парсинга.


Использование strict-парсинга

Для уменьшения количества некорректных дат применяется плагин строгого разбора:

import customParseFormat from 'dayjs/plugin/customParseFormat'
dayjs.extend(customParseFormat)

Пример строгого формата:

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

Третий аргумент true включает жёсткую проверку, исключающую несуществующие даты.


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

Частая проблема — частично заполненные строки:

  • "2024-01"
  • "2024"
  • "01-01"

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

Типовой подход:

function normalize(input) {
  if (!/^\d{4}-\d{2}-\d{2}$/.test(input)) return null;
  return dayjs(input);
}

Нормализация данных из внешних систем

При работе с API целесообразно централизовать обработку:

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

Дополнительно может применяться логирование аномалий:

if (!d.isValid()) {
  console.warn('Invalid date received:', value);
}

Влияние некорректных данных на вычисления

Некорректная дата ломает все производные вычисления:

  • diff()NaN
  • unix()NaN
  • valueOf()NaN
dayjs('bad').valueOf(); // NaN

Это особенно критично при агрегациях и сортировках:

dates.sort((a, b) => dayjs(a).valueOf() - dayjs(b).valueOf());

Наличие invalid-значений приводит к непредсказуемому порядку.


Защитные паттерны при работе с коллекциями дат

При обработке массивов используется фильтрация:

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

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

const timestamps = dates
  .map(d => dayjs(d))
  .filter(Boolean)
  .map(d => d.valueOf());

Особенности взаимодействия с UTC и плагинами

При использовании дополнительных расширений, таких как UTC, invalid-состояние сохраняется независимо от контекста:

dayjs.utc('invalid').isValid(); // false

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


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

Некорректные даты часто возникают не только из-за синтаксиса, но и из-за логических ограничений:

  • будущие даты вне диапазона системы
  • отрицательные таймстемпы
  • даты до начала эпохи Unix

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

function isReasonable(d) {
  const ts = d.valueOf();
  return ts > 0 && ts < Date.now() + 10 * 365 * 24 * 60 * 60 * 1000;
}

Роль предварительной валидации

Стабильная работа с датами строится на принципе:

  1. нормализация входа
  2. проверка формата
  3. создание объекта Day.js
  4. проверка isValid()
  5. только затем вычисления

Игнорирование этого порядка приводит к распространению invalid-объектов по всей бизнес-логике и нарушению детерминированности вычислений.