Расчет бизнес-дней

Moment.js предоставляет мощный и гибкий инструментарий для работы с датами и временем в JavaScript. Одной из частых задач в корпоративной разработке является расчет бизнес-дней — количества рабочих дней между двумя датами с учетом выходных и, при необходимости, праздничных дней.


Основные понятия

Бизнес-день — это день недели, который считается рабочим. По умолчанию в большинстве стран рабочими считаются с понедельника по пятницу, а суббота и воскресенье — выходные. Для точного расчета необходимо учитывать:

  • Выходные дни (обычно суббота и воскресенье)
  • Праздники (фиксированные или плавающие даты)
  • Начальную и конечную даты включительно или исключительно

Moment.js в базовой версии не предоставляет встроенных функций для работы с бизнес-днями, поэтому для таких расчетов часто используют расширение moment-business-days.


Установка moment-business-days

npm install moment moment-business-days

Подключение в коде:

const moment = require('moment-business-days');

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


Настройка выходных и праздников

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

moment.updateLocale('en', {
    workingWeekdays: [1, 2, 3, 4, 5] // 1 — понедельник, 5 — пятница
});

Добавление праздничных дней:

moment.updateLocale('en', {
    holidays: ['2026-01-01', '2026-12-25'],
    holidayFormat: 'YYYY-MM-DD'
});

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


Расчет количества рабочих дней между датами

Для определения количества рабочих дней используется метод .businessDiff():

const start = moment('2026-05-01', 'YYYY-MM-DD');
const end = moment('2026-05-15', 'YYYY-MM-DD');

const businessDays = end.businessDiff(start);
console.log(businessDays); // Выводит количество рабочих дней между датами

Особенности работы метода:

  • Считается разница только по рабочим дням.
  • Учитываются все настройки локали: выходные и праздники.
  • Можно менять направление расчета (от более поздней даты к более ранней).

Добавление и вычитание рабочих дней

Moment-business-days позволяет добавлять или вычитать только рабочие дни, игнорируя выходные и праздники:

let date = moment('2026-05-01', 'YYYY-MM-DD');

// Добавление 10 рабочих дней
date = date.businessAdd(10);
console.log(date.format('YYYY-MM-DD'));

// Вычитание 5 рабочих дней
date = date.businessSubtract(5);
console.log(date.format('YYYY-MM-DD'));

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


Проверка, является ли день рабочим

Для фильтрации и валидации дат можно использовать метод .isBusinessDay():

const date = moment('2026-05-02', 'YYYY-MM-DD');
if (date.isBusinessDay()) {
    console.log('Это рабочий день');
} else {
    console.log('Это выходной или праздник');
}

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


Пример использования для генерации графика задач

Допустим, необходимо создать список всех рабочих дней между двумя датами:

let start = moment('2026-05-01', 'YYYY-MM-DD');
const end = moment('2026-05-15', 'YYYY-MM-DD');
let businessDaysList = [];

while (start.isBefore(end) || start.isSame(end, 'day')) {
    if (start.isBusinessDay()) {
        businessDaysList.push(start.format('YYYY-MM-DD'));
    }
    start.add(1, 'day');
}

console.log(businessDaysList);

Результат — массив дат, включающих только рабочие дни, что удобно для планирования задач, дедлайнов и отчетов.


Учет праздничных дней и гибкие сценарии

Можно создавать динамические календари для расчета бизнес-дней в разных странах:

moment.updateLocale('ru', {
    workingWeekdays: [1, 2, 3, 4, 5],
    holidays: ['2026-01-01', '2026-05-01', '2026-12-31'],
    holidayFormat: 'YYYY-MM-DD'
});

const start = moment('2026-04-28');
const end = moment('2026-05-05');

const businessDaysCount = end.businessDiff(start);
console.log(businessDaysCount); // Учитывает российские праздники

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


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

  • Для большого объема данных лучше создать массив рабочих дней один раз и использовать его повторно.
  • Избегать вызова .businessDiff() внутри циклов по каждой дате, если можно рассчитать диапазон заранее.
  • Настройка локали (updateLocale) применяется глобально, поэтому для разных сценариев можно создать отдельные экземпляры Moment с разными локалями.

Заключение по функционалу

Использование Moment.js совместно с расширением moment-business-days позволяет:

  • Точно рассчитывать количество рабочих дней между датами.
  • Добавлять или вычитать рабочие дни без ошибок.
  • Проверять, является ли день рабочим.
  • Создавать гибкие календари с учетом праздников и локальных особенностей.

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