Разница в рабочих днях

В библиотеке date-fns работа с календарными датами строится вокруг чистых функций, каждая из которых решает строго определённую задачу. Одной из таких функций является вычисление разницы между датами с учётом только рабочих дней — выходные и праздничные периоды исключаются из расчёта.

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

Понятие рабочих дней

Рабочими днями считаются дни недели, которые не относятся к выходным. В стандартной модели:

  • понедельник — рабочий день
  • вторник — рабочий день
  • среда — рабочий день
  • четверг — рабочий день
  • пятница — рабочий день
  • суббота — выходной
  • воскресенье — выходной

В библиотеке date-fns этот подход реализован через функции, которые опираются на внутреннюю модель календаря без учёта праздников (если они не заданы отдельно через дополнительные механизмы приложения).

Основная функция differenceInBusinessDays

Ключевая функция для расчёта разницы в рабочих днях:

differenceInBusinessDays(dateLeft, dateRight)

Синтаксис

  • dateLeft — конечная дата
  • dateRight — начальная дата
  • возвращаемое значение — количество рабочих дней между датами

Функция возвращает целое число, которое может быть:

  • положительным — если dateLeft позже dateRight
  • отрицательным — если dateLeft раньше dateRight
  • нулём — если разница отсутствует или обе даты попадают в один и тот же рабочий день

Принцип работы

Алгоритм вычисления в date-fns основан на последовательном определении каждого дня между двумя датами с фильтрацией:

  1. вычисляется полный диапазон дат
  2. каждый день проверяется на принадлежность к выходным
  3. учитываются только дни с понедельника по пятницу
  4. результат агрегируется в итоговое число

Фактически функция эквивалентна подсчёту количества “активных” дней между двумя точками календаря.

Базовые примеры использования

Простая разница в пределах одной недели

import { differenceInBusinessDays } from 'date-fns'

const start = new Date(2026, 0, 5) // понедельник
const end = new Date(2026, 0, 12)  // понедельник следующей недели

differenceInBusinessDays(end, start)
// 5

В данном случае учитываются только рабочие дни: понедельник–пятница.

Диапазон с выходными внутри

const start = new Date(2026, 0, 8) // четверг
const end = new Date(2026, 0, 15)  // четверг следующей недели

differenceInBusinessDays(end, start)
// 5

Несмотря на то, что календарная разница составляет 7 дней, два выходных дня исключаются.

Обратный порядок дат

const start = new Date(2026, 0, 15)
const end = new Date(2026, 0, 8)

differenceInBusinessDays(end, start)
// -5

Отрицательный результат отражает направление интервала.

Поведение на границах дней

В date-fns даты сравниваются с точностью до дня, игнорируя время внутри суток.

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

  • 2026-01-10 00:00 и 2026-01-10 23:59 считаются одним днём
  • переход через полночь не создаёт дополнительного рабочего дня
  • результат зависит только от календарной части даты

Исключение выходных

По умолчанию выходными считаются:

  • суббота
  • воскресенье

Функция не учитывает государственные праздники, поскольку в базовой модели date-fns отсутствует встроенный календарь праздников. Для таких случаев применяется внешняя логика на уровне приложения.

Практические сценарии применения

Расчёт сроков выполнения задач

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

differenceInBusinessDays(deadline, createdAt)

Это позволяет игнорировать периоды, когда работа фактически не выполняется.

Логистика и доставка

При расчёте сроков доставки:

  • календарная разница завышает реальное время
  • рабочие дни отражают операционную нагрузку
differenceInBusinessDays(deliveryDate, shipmentDate)

Финансовые расчёты

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

  • расчёта процентов
  • определения сроков платежей
  • учёта банковских операций

Особенности при работе с локализацией

В базовой реализации date-fns неделя всегда имеет фиксированную структуру (понедельник–воскресенье), независимо от региона.

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

  • модель рабочих дней универсальна
  • локализация влияет только на форматирование дат
  • календарная логика остаётся неизменной

Сравнение с календарной разницей

В отличие от differenceInDays, функция differenceInBusinessDays исключает выходные:

  • календарная разница: учитывает все дни
  • рабочая разница: учитывает только будни

Пример:

differenceInDays(end, start) // 7
differenceInBusinessDays(end, start) // 5

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

Поведение при одинаковых датах

differenceInBusinessDays(date, date)
// 0

Если обе даты совпадают и приходятся на рабочий день, результат всегда нулевой, поскольку интервал отсутствует.

Внутренняя модель расчёта

Логика date-fns оптимизирована и не требует ручной итерации по каждому дню в пользовательском коде. Вместо этого используется математическая нормализация диапазона:

  • вычисление количества полных недель
  • добавление остаточных дней
  • исключение выходных паттернов

Такой подход делает функцию предсказуемой по производительности даже на больших диапазонах дат.

Типовые ошибки при использовании

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

  • ожидание учёта праздников без дополнительной логики
  • путаница между differenceInDays и differenceInBusinessDays
  • неправильное понимание направления аргументов
  • игнорирование того, что результат может быть отрицательным

Корректная работа требует чёткого понимания семантики рабочих дней в рамках модели date-fns.