В библиотеке date-fns вычисление разницы между датами строится вокруг календарной логики, а не абсолютного количества миллисекунд. Это означает, что месяцы и годы интерпретируются как календарные единицы, а не как фиксированное число дней.
Для работы с разницей в месяцах и годах используются две группы функций:
differenceInMonths / differenceInYears —
вычисление полных интерваловdifferenceInCalendarMonths /
differenceInCalendarYears — календарная разница по границам
периодовКлючевая идея:
месяцы и годы не имеют фиксированной длительности в днях, поэтому результат зависит от выбранной семантики вычисления.
Функция вычисляет количество полных месяцев между двумя датами.
import { differenceInMonths } from "date-fns";
const result = differenceInMonths(
new Date(2024, 5, 15),
new Date(2024, 2, 15)
);
console.log(result); // 3
Алгоритм:
Если конечный день месяца меньше исходного, последний месяц может не засчитываться как полный.
differenceInMonths(
new Date(2024, 2, 31),
new Date(2024, 1, 28)
);
Результат может отличаться от интуитивного ожидания, так как учитывается календарная корректность, а не «30 дней = месяц».
Функция возвращает разницу по календарным месяцам без учёта «полноты» периода.
import { differenceInCalendarMonths } from "date-fns";
const result = differenceInCalendarMonths(
new Date(2024, 5, 15),
new Date(2024, 2, 31)
);
console.log(result); // 3
| Функция | Логика | Особенность |
|---|---|---|
| differenceInMonths | только полные месяцы | учитывает неполные периоды |
| differenceInCalendarMonths | разница календарных месяцев | игнорирует «полноту» |
Обе функции поддерживают направление вычисления:
differenceInMonths(A, B) === -differenceInMonths(B, A)
Это правило делает поведение симметричным.
Функция вычисляет количество полных лет между датами.
import { differenceInYears } from "date-fns";
const result = differenceInYears(
new Date(2030, 0, 1),
new Date(2025, 0, 1)
);
console.log(result); // 5
differenceInYears(
new Date(2025, 11, 31),
new Date(2024, 0, 1)
);
Результат может быть 1 или 0 в зависимости
от того, завершился ли полный годовой цикл по календарным правилам.
Возвращает разницу именно по календарным годам.
import { differenceInCalendarYears } from "date-fns";
const result = differenceInCalendarYears(
new Date(2030, 6, 1),
new Date(2025, 11, 31)
);
console.log(result); // 5
| Функция | Поведение |
|---|---|
| differenceInYears | считает только полные годы |
| differenceInCalendarYears | считает смену календарных лет |
Это приводит к различию между:
differenceInMonths, differenceInYears
differenceInCalendarMonths,
differenceInCalendarYears
Февраль делает вычисления неоднозначными:
differenceInMonths(
new Date(2024, 2, 31),
new Date(2024, 1, 29)
);
Високосные и невисокосные годы могут давать разные результаты.
differenceInMonths(
new Date(2025, 0, 1),
new Date(2024, 11, 31)
);
Несмотря на разницу в 1 день, результат может быть 0,
так как полный месяц не завершён.
differenceInYears(A, B)
differenceInYears(B, A)
Результат всегда меняет знак, сохраняя модуль значения.
При работе с месяцами и годами часто используются дополнительные функции:
addMonths, subMonthsaddYears, subYearsstartOfMonth, endOfMonthstartOfYear, endOfYearКомбинация этих функций позволяет строить стабильные календарные вычисления без ручной арифметики.
Хотя месяцы и годы логически не зависят от времени суток, в JavaScript возможны пограничные эффекты:
Date(year, month, day)date-fns нормализует такие ситуации через внутреннюю работу с
Date, но логика остаётся календарной.
differenceIn* — строгий учёт завершённых периодовdifferenceInCalendar* — ориентир на смену календарных
единиц