ISO-недели

ISO-недели основаны на международном стандарте ISO 8601, который определяет единый подход к разбиению года на недели. В отличие от локальных календарных систем, где неделя может начинаться с воскресенья или понедельника, ISO-неделя всегда начинается с понедельника. Первая ISO-неделя года — это та неделя, которая содержит первый четверг января. Такое определение приводит к тому, что первые и последние дни календарного года могут относиться к соседним ISO-годам.

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


Подключение и активация ISO-недель в Day.js

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

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

dayjs.extend(isoWeek)

После расширения функциональности становятся доступными методы, работающие в соответствии с ISO 8601.


Отличие ISO-недель от локальных недель

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

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

ISO-недели фиксируют правила:

  • неделя всегда начинается в понедельник;
  • первая неделя года содержит 4 января или первый четверг года;
  • каждая неделя строго принадлежит одному ISO-годy.

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


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

После подключения плагина становится доступен метод isoWeek() для получения номера недели.

dayjs('2024-01-03').isoWeek() // пример результата: 1
dayjs('2024-12-31').isoWeek()

Метод возвращает порядковый номер недели в рамках ISO-года.

В отличие от локального метода week(), результат всегда соответствует стандарту ISO 8601.


Получение ISO-года недели

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

Для получения ISO-года используется метод isoWeekYear():

dayjs('2024-01-01').isoWeekYear()
dayjs('2023-12-31').isoWeekYear()

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


Установка недели в формате ISO

Метод isoWeek() в Day.js работает в двух режимах: получения и установки.

dayjs().isoWeek(10)

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

Комбинирование с isoWeekYear() позволяет точно позиционировать дату в рамках недельной системы:

dayjs().isoWeekYear(2025).isoWeek(1)

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

Для работы с границами недели используются методы startOf и endOf, дополненные ISO-логикой через плагин.

dayjs('2024-05-15').startOf('isoWeek')
dayjs('2024-05-15').endOf('isoWeek')

Результаты:

  • startOf('isoWeek') возвращает понедельник текущей ISO-недели;
  • endOf('isoWeek') возвращает воскресенье текущей ISO-недели.

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


Форматирование дат с ISO-неделями

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

  • W — номер недели (локальный стандарт)
  • WW — номер недели с ведущим нулём
  • GGGG — ISO-год недели
  • WW в сочетании с ISO-плагином может использоваться для отображения ISO-недель

Пример:

dayjs('2024-01-03').format('GGGG-[W]WW')

Результат может выглядеть как:

2024-W01

Сравнение week и isoWeek

Различия между локальными и ISO-неделями проявляются при сравнении методов:

import weekOfYear from 'dayjs/plugin/weekOfYear'
dayjs.extend(weekOfYear)

dayjs('2024-01-01').week()
dayjs('2024-01-01').isoWeek()

Типичные расхождения:

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

Перенос даты между ISO-неделями

Изменение недели через isoWeek() приводит к перерасчету даты с сохранением дня недели:

dayjs('2024-06-10').isoWeek(20)

Внутренний алгоритм:

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

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


Работа с диапазонами ISO-недель

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

const start = dayjs().isoWeek(1).startOf('isoWeek')
const end = dayjs().isoWeek(1).endOf('isoWeek')

Полученные значения удобно использовать для фильтрации событий:

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

Переход между ISO-годами

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

dayjs('2020-12-31').isoWeekYear() // может вернуть 2020 или 2021 в зависимости от недели

Аналогично, начало января может принадлежать предыдущему ISO-году:

dayjs('2024-01-01').isoWeekYear()

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


Использование ISO-недель в бизнес-логике

ISO-недели применяются в системах, где требуется стабильная недельная структура:

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

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


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

На границах года ISO-недели могут создавать неожиданные переходы:

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

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

Это поведение следует учитывать при:

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

Совместимость с другими плагинами Day.js

ISO-недели часто используются вместе с другими расширениями:

  • weekOfYear — локальные недели;
  • utc — унификация временных зон;
  • customParseFormat — разбор нестандартных дат.

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

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

dayjs.extend(utc)
dayjs.extend(isoWeek)

Влияние локали на ISO-недели

ISO-недели полностью независимы от локали. Даже при смене языка или региональных настроек:

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

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