Календарный год определяется исключительно границами григорианского
календаря: с 1 января по 31 декабря. Любая дата внутри этого диапазона
принадлежит одному и тому же году независимо от того, на какую неделю
она попадает и как распределяются недели по ISO-правилам. В Day.js это
значение возвращается через метод year() и соответствует
привычному представлению даты в календарной системе.
\text{year = calendar_year (Jan 1 Dec 31)
Календарный год удобно использовать в бизнес-логике, где важна привязка к финансовым периодам, отчётности, архивированию данных и любым операциям, зависящим от стандартного гражданского календаря. Однако он начинает давать неточности в задачах, где данные группируются по неделям, особенно если используется ISO-нормализация недель.
Недельный год (week-year) строится не вокруг 1 января, а вокруг системы нумерации недель. В ISO-8601 неделя:
Из этого следует ключевое свойство: первая или последняя неделя января может относиться к предыдущему или следующему году.
\text{week_year calendar_year (в граничных датах)
В Day.js недельный год доступен через плагины, связанные с ISO-неделями. Чаще всего используются:
isoWeek — расширяет работу с неделями по
ISO-правиламweekYear — добавляет методы получения недельного
годаisoWeekYear как более явная ISO-версияГлавное различие между календарным и недельным годом проявляется в конце декабря и начале января.
Рассмотрим дату: 31 декабря.
В зависимости от того, на какую неделю она попадает по ISO-логике, она может принадлежать следующему недельному году.
Пример логики:
Обратная ситуация возможна в начале января:
Это приводит к ситуации, когда одна и та же дата «живет» в двух разных годовых системах.
Для работы с недельным годом необходимо расширить Day.js соответствующими плагинами:
import dayjs from 'dayjs'
import isoWeek from 'dayjs/plugin/isoWeek'
import weekYear from 'dayjs/plugin/weekYear'
dayjs.extend(isoWeek)
dayjs.extend(weekYear)
После подключения становятся доступны методы работы с ISO-неделями и недельным годом.
Day.js разделяет два независимых измерения времени:
year() — календарный годweekYear() — год, определяемый системой недельdayjs('2025-12-31').year() // 2025
dayjs('2025-12-31').weekYear() // может быть 2026
Ключевая проблема, которую решает weekYear(),
заключается в корректной группировке данных по неделям. Если отчёт
строится по неделям, использование year() приводит к
разрыву логики: последняя неделя декабря может оказаться в одном году, а
первые дни января — в другом, хотя по недельной структуре это одна
сущность.
ISO-неделя определяется не только началом в понедельник, но и строгим правилом первой недели года:
Это правило создаёт смещение границ года относительно календаря.
Из-за этого смещения недельный год не синхронизирован с календарным на 100%.
Дата: 29 декабря 2024
Дата: 2 января 2026
Таким образом, недельный год формирует непрерывные недельные блоки, даже если они пересекают границы календаря.
При работе с аналитикой данные часто группируются по времени. Различие между календарным и недельным годом приводит к разным результатам агрегации.
Если использовать календарный год:
Если использовать недельный год:
const d = dayjs('2025-12-31')
const calendar = {
year: d.year()
}
const weekBased = {
weekYear: d.weekYear(),
week: d.isoWeek()
}
Такой подход позволяет строить отчёты по неделям без логических разрывов.
Недельный год всегда используется вместе с номером недели:
isoWeek() — номер неделиweekYear() — год этой неделиКомбинация этих значений образует уникальный идентификатор периода:
const d = dayjs('2025-12-31')
const period = `${d.weekYear()}-W${d.isoWeek()}`
Это критично для систем, где важно уникально идентифицировать недели в многолетнем диапазоне.
Основные проблемы возникают при смешивании календарного и недельного подходов:
Использование year() с isoWeek() →
недели разъезжаются по разным годам
Группировка по дате без учёта недельной логики → нарушается целостность временных интервалов
Хранение week-number без week-year → невозможность однозначно восстановить период
Корректная модель всегда включает пару: недельный год + номер недели.
Day.js опирается на неизменяемую структуру объекта даты. При подключении плагинов добавляются вычисляемые представления времени, но сама дата остаётся неизменной.
Это означает:
year() — прямое чтение календарного компонентаweekYear() — вычисляемое значение на основе
ISO-алгоритмаТакое разделение позволяет безопасно работать с разными временными системами параллельно.
На больших диапазонах данных (несколько лет) различие становится более заметным:
Это приводит к тому, что недельный год иногда имеет 53 недели вместо 52, что полностью нормально в ISO-логике и связано с распределением дней по неделям.
52
Календарный год — это административная и человеческая система отсчёта времени.
Недельный год — это структурная система, оптимизированная под равномерное разбиение времени на недели.
Day.js предоставляет обе модели одновременно, позволяя переключаться между ними в зависимости от задачи без преобразования даты в сторонние структуры.