В библиотеке Luxon работа с датами строится вокруг объекта
DateTime, который предоставляет неизменяемую (immutable)
модель времени. Каждое изменение даты или времени возвращает новый
экземпляр, что упрощает построение предсказуемой логики для календарных
вычислений, включая определение рабочих и выходных дней.
Ключевым элементом для классификации дней недели является свойство
weekday, возвращающее числовое значение от 1 до 7, где
понедельник соответствует 1, а воскресенье — 7.
import { DateTime } from "luxon";
const dt = DateTime.local();
console.log(dt.weekday);
Такое представление позволяет формализовать календарную логику без зависимости от локализованных строковых названий дней.
Наиболее распространённая модель рабочего календаря предполагает, что рабочими днями считаются дни с понедельника по пятницу, а выходными — суббота и воскресенье.
Условие проверки выходного дня сводится к анализу значения
weekday:
function isWeekend(date) {
return date.weekday >= 6;
}
Соответственно, определение рабочего дня:
function isWorkday(date) {
return date.weekday >= 1 && date.weekday <= 5;
}
Такой подход не зависит от локали и сохраняет стабильность поведения при смене часовых поясов или языковых настроек.
При обработке календарных интервалов часто требуется выделить только рабочие дни из последовательности дат. Luxon предоставляет удобный механизм генерации диапазонов через ручное увеличение даты.
import { DateTime } from "luxon";
function getDateRange(start, end) {
const dates = [];
let current = start;
while (current <= end) {
dates.push(current);
current = current.plus({ days: 1 });
}
return dates;
}
const start = DateTime.local(2026, 1, 1);
const end = DateTime.local(2026, 1, 31);
const workdays = getDateRange(start, end).filter(d => d.weekday <= 5);
Фильтрация через weekday является наиболее прямолинейным
способом выделения рабочих дней без дополнительной календарной
логики.
В Luxon объект DateTime всегда связан с временной зоной.
Это критически важно при вычислении рабочих дней в распределённых
системах, где сервер и пользователь могут находиться в разных часовых
поясах.
const dt = DateTime.now().setZone("Europe/Moscow");
console.log(dt.weekday);
При смене зоны значение календарного дня может измениться, если локальное время пересекает границу суток. Поэтому определение рабочего дня всегда должно выполняться в контексте конкретной временной зоны.
В реальных системах рабочие дни определяются не только днями недели, но и набором фиксированных или плавающих праздничных дат. Luxon не содержит встроенного календаря праздников, поэтому используется дополнительная структура данных.
Обычно праздничные дни хранятся в формате ISO:
const holidays = new Set([
"2026-01-01",
"2026-03-08",
"2026-05-01"
]);
Проверка рабочего дня с учётом праздников:
function isBusinessDay(date, holidays) {
const iso = date.toISODate();
return date.weekday <= 5 && !holidays.has(iso);
}
Использование toISODate() обеспечивает нормализованное
сравнение без учёта времени.
При генерации графиков работы или расчёте сроков часто требуется получить список только рабочих дат в заданном интервале.
function getBusinessDays(start, end, holidays) {
const result = [];
let current = start;
while (current <= end) {
if (isBusinessDay(current, holidays)) {
result.push(current);
}
current = current.plus({ days: 1 });
}
return result;
}
Такая функция формирует последовательность, пригодную для расчётов SLA, планирования задач или построения расписаний.
Одна из типовых операций — вычисление даты, отстоящей на N рабочих
дней вперёд. Простое прибавление дней через
plus({ days: N }) не учитывает выходные и праздники,
поэтому требуется итеративный подход.
function addBusinessDays(start, count, holidays) {
let current = start;
let added = 0;
while (added < count) {
current = current.plus({ days: 1 });
if (isBusinessDay(current, holidays)) {
added++;
}
}
return current;
}
Алгоритм опирается на последовательное продвижение по календарю с проверкой каждого дня.
Обратная операция реализуется симметрично, с движением в обратном направлении:
function subtractBusinessDays(start, count, holidays) {
let current = start;
let subtracted = 0;
while (subtracted < count) {
current = current.minus({ days: 1 });
if (isBusinessDay(current, holidays)) {
subtracted++;
}
}
return current;
}
Такая логика используется в системах дедлайнов, ретроспективных расчётах и финансовых моделях.
При работе с пользовательскими вводами или API важно нормализовать дату до начала дня, чтобы исключить влияние времени.
const normalized = dt.startOf("day");
Это предотвращает ситуации, когда сравнение ISO-дат может быть некорректным из-за различий во времени внутри суток.
Luxon предоставляет объект Interval, который описывает
временной диапазон. Хотя он не содержит встроенной фильтрации рабочих
дней, он упрощает структурирование данных.
import { Interval } from "luxon";
const interval = Interval.fromDateTimes(start, end);
const days = [];
let cursor = interval.start;
while (cursor <= interval.end) {
days.push(cursor);
cursor = cursor.plus({ days: 1 });
}
Дальнейшая фильтрация выполняется по стандартным правилам
weekday и списку праздников.
В некоторых странах рабочая неделя отличается от классической модели 5/2. Luxon предоставляет универсальный календарный базис, но бизнес-логика должна учитывать региональные правила.
Пример конфигурационной модели:
const calendarConfig = {
workweek: [1, 2, 3, 4, 5], // может быть изменено
holidays: new Set()
};
function isWorkdayCustom(date, config) {
return config.workweek.includes(date.weekday) &&
!config.holidays.has(date.toISODate());
}
Такой подход позволяет адаптировать расчёты под любую юрисдикцию без изменения базовой логики.
Luxon активно использует ISO-форматы (toISO,
toISODate) для сериализации дат. Это особенно важно при
хранении списков рабочих и праздничных дней в базах данных.
const isoDate = DateTime.local().toISODate();
Использование стандартизированного формата упрощает сравнение и исключает проблемы локализации.
При частых проверках рабочих дней имеет смысл предварительно вычислять диапазоны и кэшировать результаты. Это особенно эффективно при больших интервалах дат.
const cache = new Map();
function isBusinessDayCached(date, holidays) {
const key = date.toISODate();
if (cache.has(key)) return cache.get(key);
const result = date.weekday <= 5 && !holidays.has(key);
cache.set(key, result);
return result;
}
Такая оптимизация снижает количество повторных вычислений при массовой обработке календарей.
На практике определение рабочих дней редко существует изолированно.
Оно становится частью более сложных вычислений: расчёта сроков задач,
формирования графиков, планирования ресурсов и финансовых моделей. Luxon
обеспечивает стабильную основу через DateTime,
weekday, plus и minus, а
бизнес-правила формируют надстройку над этой моделью, определяя
конкретное поведение календаря в системе.