ISO-недельный календарь основан на стандарте ISO 8601 и отличается от привычного календарного представления тем, как группируются недели и определяется их принадлежность к году. Неделя всегда начинается с понедельника, а первая неделя года — это та, которая содержит первый четверг января (или 4 января). Такая система обеспечивает стабильность нумерации недель между годами и широко используется в бизнес-аналитике, планировании и отчетности.
В JavaScript через Date-fns работа с ISO-неделями выделена в отдельный набор функций, обеспечивающих корректное вычисление границ недель, их номеров и соответствие ISO-годам.
Для получения границ ISO-недели используются функции, которые учитывают смещение относительно понедельника.
Начало ISO-недели:
import { startOfISOWeek } from 'date-fns';
startOfISOWeek(new Date(2026, 0, 15));
Функция возвращает дату понедельника, соответствующего ISO-неделе, в которую входит указанная дата. В отличие от обычного недельного вычисления, здесь всегда фиксирован старт на понедельник вне зависимости от локальных настроек.
Конец ISO-недели:
import { endOfISOWeek } from 'date-fns';
endOfISOWeek(new Date(2026, 0, 15));
Результатом является воскресенье той же ISO-недели с установкой времени на конец дня (23:59:59.999).
ISO-неделя определяется относительно ISO-года, а не календарного года.
import { getISOWeek } from 'date-fns';
getISOWeek(new Date(2026, 0, 15));
Результатом будет число от 1 до 53. Некоторые годы содержат 53 недели, что связано с особенностями распределения дней по ISO-правилу.
ISO-год может не совпадать с календарным годом, особенно для дат в начале января или конце декабря.
import { getISOWeekYear } from 'date-fns';
getISOWeekYear(new Date(2026, 0, 1));
Функция возвращает год, к которому относится ISO-неделя данной даты.
Функция setISOWeek позволяет сместить дату так, чтобы
она оказалась в заданной ISO-неделе текущего ISO-года.
import { setISOWeek } from 'date-fns';
setISOWeek(new Date(2026, 0, 15), 10);
В результате будет возвращена дата, соответствующая той же позиции внутри недели, но перенесённая в 10-ю ISO-неделю.
import { setISOWeekYear } from 'date-fns';
setISOWeekYear(new Date(2026, 0, 15), 2024);
Функция переносит дату в указанный ISO-год, сохраняя номер недели и позицию дня внутри недели.
Для работы с временными промежутками используется генерация последовательности ISO-недель.
import { eachISOWeek } from 'date-fns';
eachISOWeek({
start: new Date(2026, 0, 1),
end: new Date(2026, 2, 1),
});
Результатом является массив дат, каждая из которых представляет начало очередной ISO-недели в диапазоне.
ISO-неделя всегда имеет фиксированную структуру:
Эта предсказуемость делает систему удобной для аналитических вычислений и серверной обработки дат.
В отличие от календарного года, ISO-недельный год может начинаться в конце декабря предыдущего года и заканчиваться в начале января следующего.
Пример логики:
Такая модель устраняет «обрыв» недель между годами.
Часто вычисления строятся на комбинации функций:
import {
startOfISOWeek,
endOfISOWeek,
getISOWeek,
getISOWeekYear
} from 'date-fns';
const date = new Date(2026, 4, 22);
const start = startOfISOWeek(date);
const end = endOfISOWeek(date);
const weekNumber = getISOWeek(date);
const weekYear = getISOWeekYear(date);
Такая связка используется для формирования отчетных периодов, где требуется однозначная привязка к неделям.
Работа с ISO-неделями часто включает пересчёт дат относительно начала недели.
import { startOfISOWeek, addDays } from 'date-fns';
const monday = startOfISOWeek(new Date(2026, 6, 10));
const thursday = addDays(monday, 3);
Подобный подход позволяет строить недельные расписания, диаграммы нагрузки и временные сетки.
Некоторые функции JavaScript опираются на воскресенье как начало недели, что конфликтует с ISO-стандартом.
Использование getISOWeek без getISOWeekYear
приводит к неоднозначности на границах года.
Комбинация getWeek и getISOWeek даёт
некорректные результаты при переходе между годами.
| Операция | Функция |
|---|---|
| Начало недели | startOfISOWeek |
| Конец недели | endOfISOWeek |
| Номер недели | getISOWeek |
| ISO-год | getISOWeekYear |
| Установка недели | setISOWeek |
| Установка года | setISOWeekYear |
| Генерация диапазона | eachISOWeek |
ISO-недельные данные часто используются вместе с форматированием:
import { format, getISOWeek } from 'date-fns';
const date = new Date(2026, 8, 18);
format(date, 'yyyy-MM-dd');
getISOWeek(date);
Такая комбинация применяется для построения подписей осей графиков, отчётных таблиц и календарных сеток.
Граничные даты требуют особого внимания:
getISOWeek(new Date(2026, 11, 31));
getISOWeek(new Date(2026, 0, 1));
Обе даты могут принадлежать одной ISO-неделе, но разным календарным годам. Это ключевое отличие, определяющее корректность аналитических систем.
При группировке данных по неделям используется связка ISO-недели и ISO-года как составной ключ:
const key = `${getISOWeekYear(date)}-W${getISOWeek(date)}`;
Такой ключ исключает коллизии между одинаковыми номерами недель в разных годах.
ISO-недели часто становятся базой для сеток планирования:
Последовательное использование eachISOWeek позволяет
формировать оси времени без пропусков и дублирования недель.