Обработка значений null и undefined в
date-fns напрямую связана с тем, как JavaScript представляет отсутствие
данных и как библиотека интерпретирует некорректные или неполные даты. В
отличие от более «толерантных» утилит, date-fns придерживается строгой
модели: большинство функций ожидают валидный объект Date,
timestamp или строку, которую можно однозначно преобразовать в дату.
При передаче null или undefined в функции
date-fns поведение зависит от конкретной функции, но общая логика
сводится к нескольким сценариям:
Invalid DateNaN (для арифметических операций)RangeErrorПример:
import { format } from 'date-fns';
format(null, 'yyyy-MM-dd');
// Invalid Date или RangeError (в зависимости от версии и окружения)
format(undefined, 'yyyy-MM-dd');
// аналогичное поведение: ошибка или Invalid Date
Главная причина такого поведения заключается в том, что внутри
date-fns происходит приведение входного значения к объекту
Date:
new Date(value)
Для null это превращается в new Date(null)
→ валидная дата эпохи (1970-01-01), тогда как
new Date(undefined) → Invalid Date. Однако
date-fns дополнительно валидирует результат, и итоговое поведение
становится более строгим.
В JavaScript эти значения имеют разную семантику:
null — явное отсутствие значенияundefined — неопределённость или
неинициализированностьВ date-fns это приводит к разным результатам на уровне преобразования:
new Date(null); // Thu Jan 01 1970
new Date(undefined); // Invalid Date
Однако многие функции date-fns не доверяют «частично валидным» датам и дополнительно проверяют корректность через внутренние механизмы.
Большинство функций date-fns при некорректном входе возвращают объект
Invalid Date. Он формально является объектом
Date, но его числовое представление — NaN:
const d = new Date('invalid');
Number(d); // NaN
Функции, выполняющие вычисления, начинают «распространять» NaN:
import { differenceInDays } from 'date-fns';
differenceInDays(null, new Date());
// NaN
Это поведение критично: ошибка не всегда проявляется сразу, а проявляется в цепочке вычислений.
Функции типа differenceIn*, add*,
sub* используют внутреннее преобразование даты. При
получении null или undefined результат почти
всегда становится NaN.
differenceInDays(undefined, undefined);
// NaN
addDays(null, 5);
// Invalid Date или NaN в дальнейших операциях
Причина заключается в том, что вычисления базируются на timestamp:
getTime(date)
Если date невалидна, getTime() возвращает
NaN, что «ломает» всю цепочку.
Функция format наиболее чувствительна к некорректным
значениям.
import { format } from 'date-fns';
format(undefined, 'dd.MM.yyyy');
format(null, 'dd.MM.yyyy');
Обе ситуации приводят к ошибкам, так как форматирование требует валидной даты.
Внутри происходит цепочка:
DateЕсли на этапе (2) обнаруживается Invalid Date,
выполнение прерывается.
Ключевой механизм защиты от null и
undefined — функция isValid:
import { isValid } from 'date-fns';
isValid(null); // false
isValid(undefined); // false
isValid(new Date()); // true
isValid проверяет числовое представление даты:
Number(date) !== NaN
или более точно:
!isNaN(date.getTime())
Функция parseISO ожидает строку ISO-формата. При
передаче null или undefined происходит
преобразование к строке:
parseISO(null); // Invalid Date
parseISO(undefined); // Invalid Date
Это связано с тем, что:
String(null) // "null"
String(undefined) // "undefined"
Обе строки не являются корректными ISO-датами.
Данные из API часто содержат null в полях дат:
{
"createdAt": null
}
При прямой передаче в date-fns возникает каскадная ошибка. Поэтому обычно применяется нормализация:
const safeDate = value ? new Date(value) : null;
или:
const safeDate = value ?? undefined;
Но даже после этого требуется проверка:
if (!safeDate || !isValid(safeDate)) {
// обработка отсутствующей даты
}
Часто используется паттерн с дефолтами:
function formatSafe(date) {
if (!date) return '';
if (!isValid(date)) return '';
return format(date, 'dd.MM.yyyy');
}
или через раннюю нормализацию:
const toDateOrNull = (value) => {
if (value === null || value === undefined) return null;
const d = new Date(value);
return isNaN(d.getTime()) ? null : d;
};
date-fns часто используется в композиции:
format(addDays(parseISO(value), 2), 'dd.MM.yyyy');
При value = null происходит цепочка:
parseISO(null) → Invalid DateaddDays(Invalid Date, 2) → Invalid Dateformat(Invalid Date) → ошибка или Invalid DateОшибка не всегда возникает на первом шаге, что усложняет отладку.
Функции сравнения также чувствительны:
import { isBefore } from 'date-fns';
isBefore(null, new Date()); // false или ошибка
Если хотя бы один аргумент невалиден, результат теряет смысл и может быть непредсказуемым.
Наиболее проблемные ситуации:
''null из APIundefined из необязательных полей{ year: null, month: undefined }Все они приводят к одному базовому состоянию —
Invalid Date.
Основной подход заключается в том, чтобы никогда не передавать необработанные значения:
isValidnull как маркера отсутствия даты вместо
Invalid DateТак формируется предсказуемая модель обработки времени, где
null и undefined не становятся источником
скрытых ошибок в вычислениях и форматировании.