Начало и конец ISO-недели

ISO-неделя (ISO 8601 week) отличается от календарной недели тем, что фиксирует единое правило начала и нумерации: неделя всегда начинается в понедельник, а заканчивается в воскресенье. Это устраняет различия между региональными календарями и делает расчёты дат предсказуемыми при работе с бизнес-логикой, отчётами и временными интервалами.

В JavaScript-библиотеке Day.js работа с ISO-неделями реализуется через подключение соответствующего плагина, после чего становятся доступны методы, ориентированные на ISO-стандарт. Основной смысл этой функциональности — корректное вычисление границ недели независимо от локальных настроек среды.

Перед использованием операций с ISO-неделями необходимо подключить плагин:

import dayjs from 'dayjs'
import isoWeek from 'dayjs/plugin/isoWeek'

dayjs.extend(isoWeek)

После расширения экземпляра Day.js появляются методы, учитывающие ISO-логику. Без подключения плагина попытка использовать ISO-недели приведёт к отсутствию соответствующих методов или к поведению стандартной локальной недели.

Начало ISO-недели

Начало ISO-недели всегда фиксировано на понедельник. В Day.js это реализуется через метод startOf('isoWeek').

const date = dayjs('2026-05-22')
const start = date.startOf('isoWeek')

Результатом будет дата, приведённая к понедельнику текущей ISO-недели, с обнулением времени до 00:00:00.

Поведение метода определяется двумя ключевыми моментами:

  • используется именно ISO-логика, а не локальная неделя;
  • день недели вычисляется относительно стандарта, где понедельник имеет индекс начала цикла.

Пример:

dayjs('2026-05-22').startOf('isoWeek').format()
// 2026-05-18T00:00:00+00:00 (в зависимости от таймзоны)

Даже если локальная среда считает началом недели воскресенье или другой день, ISO-логика всегда приводит дату к понедельнику.

Внутренне Day.js вычисляет смещение относительно текущего дня недели и вычитает необходимое количество дней, чтобы попасть на понедельник. При этом также сбрасываются часы, минуты, секунды и миллисекунды, чтобы результат соответствовал началу временного интервала.

Конец ISO-недели

Конец ISO-недели фиксируется на воскресенье. Для этого используется метод endOf('isoWeek').

const date = dayjs('2026-05-22')
const end = date.endOf('isoWeek')

Результат — воскресенье текущей ISO-недели с установкой времени на 23:59:59.999.

dayjs('2026-05-22').endOf('isoWeek').format()
// 2026-05-24T23:59:59.999+00:00 (в зависимости от таймзоны)

Метод работает симметрично startOf('isoWeek'), но вместо вычитания дней выполняется добавление до ближайшего воскресенья.

Особенность заключается в том, что граница недели вычисляется не через фиксированный календарный диапазон, а через относительное положение текущей даты в недельном цикле ISO.

Логика определения ISO-недели

ISO-неделя строится по строгим правилам:

  • неделя начинается в понедельник;
  • первая неделя года — та, которая содержит первый четверг января;
  • каждая неделя имеет полный семидневный цикл.

Day.js использует эти правила при работе с ISO-методами, что позволяет корректно определять границы даже для дат на стыке годов.

Например, дата в конце декабря может относиться к первой ISO-неделе следующего года, если в ней присутствует первый четверг января.

Разница между локальной неделей и ISO-неделей

Стандартная неделя в Day.js (без ISO-плагина) зависит от локали и может начинаться в воскресенье или понедельник в зависимости от настроек. Это приводит к различиям в результатах:

dayjs('2026-05-22').startOf('week')
dayjs('2026-05-22').startOf('isoWeek')

В первом случае результат зависит от локальных правил среды. Во втором — всегда фиксирован понедельник.

Это различие критично при построении:

  • недельных отчётов;
  • аналитических панелей;
  • расчётов KPI;
  • агрегации данных по периодам.

ISO-неделя устраняет неоднозначность и делает вычисления стабильными независимо от пользователя или региона.

Получение номера ISO-недели и границ периода

Помимо начала и конца недели, Day.js позволяет работать с номером ISO-недели через метод isoWeek().

dayjs('2026-05-22').isoWeek()

Это число соответствует порядковому номеру недели в ISO-годе. В сочетании с startOf('isoWeek') и endOf('isoWeek') можно строить полноценные временные диапазоны.

Пример формирования диапазона:

const date = dayjs('2026-05-22')

const range = {
  start: date.startOf('isoWeek'),
  end: date.endOf('isoWeek')
}

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

Работа с временной зоной и точностью

При вычислении начала и конца ISO-недели важно учитывать, что Day.js оперирует объектами даты с точностью до миллисекунд. Поэтому:

  • начало недели всегда фиксируется на 00:00:00.000;
  • конец недели — на 23:59:59.999.

Это позволяет использовать значения напрямую в SQL-запросах, API-фильтрах и логике сравнения дат.

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

Особенности перехода через границы года

ISO-неделя может принадлежать году, отличному от календарного. Например, последние дни декабря могут относиться к первой ISO-неделе следующего года.

dayjs('2020-12-31').isoWeek()

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

Методы startOf('isoWeek') и endOf('isoWeek') в этих ситуациях корректно возвращают границы недели, даже если она формально относится к соседнему году.

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

При типичной задаче агрегации данных используется следующая логика:

function getIsoWeekRange(date) {
  const d = dayjs(date)

  return {
    start: d.startOf('isoWeek'),
    end: d.endOf('isoWeek')
  }
}

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

Поведение при цепочках методов

Day.js поддерживает цепочки вызовов, и ISO-недели корректно интегрируются в них:

dayjs()
  .add(10, 'day')
  .startOf('isoWeek')
  .format()

Каждый шаг пересчитывает дату заново, а ISO-логика применяется на финальном этапе вычисления границ недели.

Это важно учитывать при сложных трансформациях дат, чтобы не потерять смысл временного интервала.

Взаимодействие с другими временными единицами

ISO-неделя в Day.js хорошо сочетается с другими методами:

  • startOf('day') и endOf('day') — для суточной детализации внутри недели;
  • add() и subtract() — для переходов между неделями;
  • diff() — для расчёта расстояния между неделями.

Комбинация этих методов позволяет строить многомерные временные модели, где неделя выступает базовой единицей агрегации.

Например, разбиение диапазона на дни внутри ISO-недели:

const start = dayjs().startOf('isoWeek')

const days = Array.from({ length: 7 }, (_, i) =>
  start.add(i, 'day')
)

Каждый элемент массива будет соответствовать одному дню недели, начиная с понедельника.

Стабильность вычислений

Использование ISO-недель в Day.js обеспечивает детерминированность результатов. Независимо от системы, локали или настроек браузера:

  • начало недели всегда понедельник;
  • конец недели всегда воскресенье;
  • границы недели не зависят от региональных правил.

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