При работе с датами в JavaScript через Day.js критические ошибки чаще
всего проявляются не в типовых сценариях, а при обработке крайних
значений: минимальных и максимальных временных меток, переходов между
месяцами, високосных лет, временных зон и некорректного входного
формата. Day.js предоставляет компактный API, но сохраняет поведение
JavaScript Date, что важно учитывать при тестировании.
В основе Day.js лежит объект Date, который опирается на
диапазон времени, ограниченный реализацией ECMAScript: примерно от
-8640000000000000 до 8640000000000000
миллисекунд относительно Unix Epoch.
Типичные граничные сценарии:
import dayjs from 'dayjs';
const minDate = dayjs(-8640000000000000);
const maxDate = dayjs(8640000000000000);
console.log(minDate.isValid());
console.log(maxDate.isValid());
Проблемы возникают при:
Важно учитывать, что выход за пределы диапазона не всегда вызывает
исключение — часто возвращается Invalid Date.
Unix Epoch (1970-01-01T00:00:00Z) является ключевой
точкой для тестирования.
dayjs(0); // Epoch
dayjs(-1); // 1 миллисекунда до эпохи
dayjs(-1000 * 60 * 60); // 1 час до эпохи
Граничные дефекты проявляются при:
startOf('day') для дат до эпохи.Особенность: Day.js корректно работает с отрицательными timestamp, но поведение может отличаться в старых окружениях Node.js.
Один из наиболее чувствительных участков — 29 февраля.
dayjs('2024-02-29').isValid(); // true
dayjs('2023-02-29').isValid(); // false
Проблемные кейсы:
.add(1, 'year');dayjs('2024-02-29').add(1, 'year').format();
// часто приводит к 2025-03-01
Это связано не с Day.js, а с логикой JavaScript Date, который «перепрыгивает» на следующий корректный день.
Разная длина месяцев (28–31 день) создаёт неоднозначные сценарии.
dayjs('2023-01-31').add(1, 'month').format();
// ожидаемое: 2023-02-28 или 2023-03-03 (зависит от поведения)
Граничные случаи:
endOf('month');add → subtract → endOf.Корректное тестирование должно фиксировать ожидаемую стратегию нормализации даты.
При подключении utc и timezone плагинов
появляются дополнительные точки нестабильности.
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.tz('2024-10-27 02:30', 'Europe/Berlin');
В момент перехода на зимнее время один и тот же локальный час может быть смещён или дублирован.
DST создаёт логические разрывы в последовательности времени.
Типовые проблемы:
diff между соседними временными
точками.const a = dayjs.tz('2024-03-31 01:59', 'Europe/Berlin');
const b = dayjs.tz('2024-03-31 03:00', 'Europe/Berlin');
b.diff(a, 'minute');
Результат может отличаться от ожидаемого арифметического значения.
Day.js поддерживает ISO 8601 и ряд нестрогих форматов, но это источник неоднозначностей.
dayjs('2024-13-01'); // invalid month
dayjs('2024-00-10'); // невалидный месяц
dayjs('2024-02-30'); // несуществующая дата
Особое внимание требуется к «почти валидным» строкам:
2024-02-31 → нормализуется в март;2024/02/31 → зависит от парсера окружения;2024-2-5 → может интерпретироваться неоднозначно.Граничное тестирование должно включать:
null, undefined;Частая ошибка — смешивание единиц измерения.
dayjs(1710000000); // интерпретация как миллисекунды
dayjs.unix(1710000000); // интерпретация как секунды
Граничные случаи:
1,
10);Неверная интерпретация приводит к сдвигам на десятилетия.
Day.js является иммутабельным, но цепочки операций могут приводить к накоплению логических ошибок.
const d = dayjs('2024-01-31')
.add(1, 'month')
.add(1, 'month')
.subtract(1, 'day');
Граничные сценарии:
.add('month');startOf и endOf;Каждый шаг может нормализовать дату по-своему.
Метод diff зависит от единицы измерения и
округления.
dayjs('2024-01-01').diff('2023-12-31', 'day');
dayjs('2024-01-01').diff('2023-12-31', 'hour');
Проблемные зоны:
Граничное тестирование должно учитывать:
Метод format может скрывать внутренние проблемы
данных.
dayjs('invalid').format();
dayjs(0).format('YYYY-MM-DD HH:mm:ss');
Граничные случаи:
locale.Особенно важно проверять:
Хотя Day.js иммутабелен, тестирование часто выявляет логические ошибки в ожиданиях разработчиков.
const a = dayjs('2024-01-01');
const b = a.add(1, 'day');
console.log(a.format());
console.log(b.format());
Граничные ситуации:
Эффективное тестирование Day.js-кода обычно строится на комбинации подходов:
1. Табличные тесты
Использование фиксированных наборов дат:
[
['2024-02-29', true],
['2023-02-29', false],
['2024-13-01', false]
]
2. Проверка инвариантов
add(x).subtract(x) должно возвращать исходное значение
(с оговорками по месяцам);isValid() не должен зависеть от форматирования;startOf('day') всегда ≤ исходной даты.3. Property-based тестирование
Генерация случайных дат:
4. Тестирование переходов времени
Day.js расширяется через плагины, и порядок их подключения может влиять на результат.
Граничные сценарии:
utc + timezone +
relativeTime;Поведение Day.js зависит от среды выполнения:
Граничные ошибки часто проявляются при:
Day.js не выбрасывает исключения при ошибках парсинга, а возвращает объект с флагом невалидности.
const d = dayjs('not-a-date');
d.isValid(); // false
Граничные сценарии:
Поведение может быть неожиданным, если не проверяется
isValid() на раннем этапе.