В большинстве стран календарная неделя начинается с понедельника, а первая неделя года определяется не просто наличием 1 января. Для стандартизации был создан международный стандарт ISO 8601.
Согласно ISO 8601:
1 до 52
или 53.Moment.js предоставляет отдельный набор методов для работы именно с ISO-неделями, поскольку обычные календарные недели могут отличаться в зависимости от локали.
Метод isoWeek() возвращает номер ISO-недели.
const date = moment('2025-01-02');
console.log(date.isoWeek());
Результат:
1
week()
и isoWeek()Moment.js содержит два похожих метода:
| Метод | Основа |
|---|---|
week() |
локальные настройки |
isoWeek() |
стандарт ISO 8601 |
Пример:
const date = moment('2022-01-01');
console.log(date.week());
console.log(date.isoWeek());
В разных локалях week() может вернуть различные
значения, тогда как isoWeek() всегда следует
ISO-стандарту.
Метод isoWeek(number) позволяет изменить неделю
даты.
const date = moment('2025-01-10');
date.isoWeek(15);
console.log(date.format('YYYY-MM-DD'));
Moment.js автоматически пересчитает дату в пределах соответствующего года.
ISO-календарь использует собственное понятие года. Иногда последние дни декабря относятся уже к первой ISO-неделе следующего года.
Метод isoWeekYear() возвращает ISO-год.
const date = moment('2020-12-31');
console.log(date.isoWeekYear());
Результат:
2020
Однако:
const date = moment('2021-01-01');
console.log(date.isoWeekYear());
Результат:
2020
Хотя календарный год уже 2021, ISO-календарь всё ещё
относит дату к предыдущему ISO-году.
const date = moment();
date.isoWeekYear(2030);
console.log(date.format());
Метод isoWeekday() работает по ISO-стандарту:
| День | Значение |
|---|---|
| Понедельник | 1 |
| Вторник | 2 |
| Среда | 3 |
| Четверг | 4 |
| Пятница | 5 |
| Суббота | 6 |
| Воскресенье | 7 |
Пример:
const date = moment('2025-05-19');
console.log(date.isoWeekday());
Результат:
1
day() от
isoWeekday()Метод day() использует американскую систему:
| День | day() |
|---|---|
| Воскресенье | 0 |
| Понедельник | 1 |
| … | … |
| Суббота | 6 |
ISO-подход делает понедельник первым днём недели.
Сравнение:
const date = moment('2025-05-18');
console.log(date.day());
console.log(date.isoWeekday());
Результат:
0
7
const date = moment('2025-05-21');
date.isoWeekday(1);
console.log(date.format('YYYY-MM-DD'));
Дата будет изменена на понедельник текущей ISO-недели.
Для получения начала ISO-недели используется
startOf('isoWeek').
const date = moment('2025-05-21');
console.log(
date.startOf('isoWeek').format('YYYY-MM-DD')
);
Результат:
2025-05-19
const date = moment('2025-05-21');
console.log(
date.endOf('isoWeek').format('YYYY-MM-DD HH:mm:ss')
);
Результат:
2025-05-25 23:59:59
Moment.js поддерживает специальные токены форматирования.
| Токен | Значение |
|---|---|
W |
номер ISO-недели |
WW |
ISO-неделя с ведущим нулём |
GGGG |
ISO-год |
Пример:
const date = moment('2025-01-05');
console.log(
date.format('GGGG-[W]WW')
);
Результат:
2025-W01
const start = moment().startOf('isoWeek');
const end = moment().endOf('isoWeek');
console.log(start.format());
console.log(end.format());
const a = moment('2025-05-19');
const b = moment('2025-05-25');
console.log(
a.isoWeek() === b.isoWeek() &&
a.isoWeekYear() === b.isoWeekYear()
);
const start = moment().startOf('isoWeek');
const days = [];
for (let i = 0; i < 7; i++) {
days.push(
start.clone().add(i, 'days').format('YYYY-MM-DD')
);
}
console.log(days);
Некоторые годы содержат 53 ISO-недели.
Проверка:
const date = moment('2020-12-31');
console.log(date.isoWeek());
Результат:
53
53-я неделя появляется, если:
Особенность ISO-календаря особенно заметна на границе лет.
Пример:
| Дата | ISO-год | ISO-неделя |
|---|---|---|
| 2020-12-31 | 2020 | 53 |
| 2021-01-01 | 2020 | 53 |
| 2021-01-04 | 2021 | 1 |
Проверка:
const dates = [
'2020-12-31',
'2021-01-01',
'2021-01-04'
];
dates.forEach(d => {
const m = moment(d);
console.log(
d,
m.isoWeekYear(),
m.isoWeek()
);
});
ISO-недели широко применяются:
Пример формирования идентификатора недели:
const id = moment().format('GGGG-[W]WW');
console.log(id);
Результат:
2025-W21
Moment.js позволяет создавать дату, используя ISO-год, ISO-неделю и день недели.
const date = moment()
.isoWeekYear(2025)
.isoWeek(10)
.isoWeekday(1);
console.log(date.format('YYYY-MM-DD'));
ISO-методы полностью совместимы с UTC.
const date = moment.utc('2025-01-01');
console.log(date.isoWeek());
console.log(date.isoWeekYear());
week() вместо isoWeek()moment().week();
Такой код зависит от локали и может давать неожиданные результаты.
Для международных систем предпочтителен ISO-подход:
moment().isoWeek();
Нельзя сравнивать только номер недели.
Неправильно:
a.isoWeek() === b.isoWeek()
Правильно:
a.isoWeek() === b.isoWeek() &&
a.isoWeekYear() === b.isoWeekYear()
Неверно:
moment().format('YYYY-WW')
YYYY — обычный календарный год.
Для ISO-календаря необходимо использовать GGGG.
Правильно:
moment().format('GGGG-[W]WW')
const currentWeek = moment().isoWeek();
console.log(currentWeek);
const previousWeek = moment()
.subtract(1, 'week')
.isoWeek();
console.log(previousWeek);
const a = moment('2025-01-01');
const b = moment('2025-03-01');
console.log(
b.diff(a, 'weeks')
);
Даже при изменении локали ISO-методы остаются неизменными.
moment.locale('ru');
const date = moment();
console.log(date.isoWeek());
console.log(date.isoWeekday());
ISO-календарь всегда:
| Метод | Назначение |
|---|---|
isoWeek() |
получение/установка ISO-недели |
isoWeekYear() |
получение/установка ISO-года |
isoWeekday() |
получение/установка ISO-дня |
startOf('isoWeek') |
начало ISO-недели |
endOf('isoWeek') |
конец ISO-недели |
format('GGGG-[W]WW') |
ISO-форматирование недели |