В классическом календаре год начинается 1 января, однако во многих системах учёта используется понятие недельного года — года, основанного на неделях. В Moment.js для работы с такими значениями предусмотрен отдельный набор методов.
Недельный год особенно важен в:
Обычный год:
moment('2025-01-01').year()
возвращает:
2025
Однако недельный год может отличаться:
moment('2025-01-01').weekYear()
или:
moment('2025-01-01').isoWeekYear()
Причина заключается в том, что первая неделя года может начинаться ещё в предыдущем календарном году.
Стандарт ISO-8601 определяет:
Например:
| Дата | Календарный год | ISO-недельный год |
|---|---|---|
| 2020-12-31 | 2020 | 2020 |
| 2021-01-01 | 2021 | 2020 |
| 2021-01-04 | 2021 | 2021 |
Метод weekYear() работает с локализованным недельным
годом.
const date = moment('2025-01-01');
console.log(date.weekYear());
Метод isoWeekYear() использует ISO-стандарт.
const date = moment('2021-01-01');
console.log(date.isoWeekYear());
Результат:
2020
Потому что дата относится к последней ISO-неделе 2020 года.
const date = moment('2021-01-01');
console.log(date.year());
console.log(date.isoWeekYear());
Результат:
2021
2020
Часто год недели используется вместе с номером недели.
const date = moment('2021-01-01');
console.log(date.isoWeek());
console.log(date.isoWeekYear());
Результат:
53
2020
Moment.js поддерживает специальные токены форматирования.
moment('2021-01-01').format('GGGG')
Результат:
2020
| Токен | Описание |
|---|---|
gggg |
локальный год недели |
gg |
локальный год недели (2 цифры) |
GGGG |
ISO-год недели |
GG |
ISO-год недели (2 цифры) |
const date = moment('2021-01-01');
console.log(date.format('YYYY'));
console.log(date.format('GGGG'));
Результат:
2021
2020
const date = moment();
date.weekYear(2030);
console.log(date.format());
const date = moment();
date.isoWeekYear(2030);
console.log(date.format());
Moment.js автоматически корректирует дату в соответствии с неделей.
При изменении недельного года Moment.js:
Пример:
const date = moment('2021-01-05');
console.log(date.format());
date.isoWeekYear(2025);
console.log(date.format());
const date = moment();
date.isoWeekYear(2025);
date.isoWeek(10);
date.isoWeekday(3);
console.log(date.format());
Здесь:
isoWeekYear(2025) — ISO-год;isoWeek(10) — 10 неделя;isoWeekday(3) — среда.const date = moment()
.isoWeekYear(2025)
.isoWeek(1)
.isoWeekday(1);
console.log(date.format());
Получение первого понедельника ISO-года.
Moment.js умеет разбирать недельные даты.
const date = moment('2025-W10-3', 'GGGG-[W]WW-E');
console.log(date.format());
| Часть | Значение |
|---|---|
GGGG |
ISO-года недели |
WW |
номер недели |
E |
ISO-день недели |
Методы:
week()
weekYear()
weekday()
зависят от локали.
Например, начало недели в разных странах отличается:
ISO-методы всегда работают одинаково:
isoWeek()
isoWeekYear()
isoWeekday()
Это делает их предпочтительными для международных систем.
moment().weeksInYear()
moment().isoWeeksInYear()
console.log(moment('2020').isoWeeksInYear());
console.log(moment('2021').isoWeeksInYear());
Результат:
53
52
53 недели появляются, если:
const date = moment('2021-01-01');
if (date.isoWeekYear() === 2020) {
console.log('Дата относится к ISO-году 2020');
}
Для отчётов часто используется комбинированный ключ:
const key = moment().format('GGGG-[W]WW');
Пример результата:
2025-W08
Такой формат удобен для:
const start = moment()
.isoWeekYear(2025)
.startOf('isoWeek');
console.log(start.format());
const end = moment()
.isoWeekYear(2025)
.isoWeek(moment().isoWeeksInYear())
.endOf('isoWeek');
console.log(end.format());
const a = moment('2021-01-01');
const b = moment('2020-12-31');
console.log(
a.isoWeekYear() === b.isoWeekYear()
);
Частый сценарий:
const reportDate = moment();
const reportKey = {
year: reportDate.isoWeekYear(),
week: reportDate.isoWeek()
};
console.log(reportKey);
const group = moment(date)
.format('GGGG-[W]WW');
Пример:
2025-W14
При использовании moment-timezone недельный год зависит
от временной зоны.
const date = moment.tz(
'2021-01-01 01:00',
'Europe/Berlin'
);
console.log(date.isoWeekYear());
Неправильно:
moment().format('YYYY-WW')
Правильно:
moment().format('GGGG-[W]WW')
Нежелательно смешивать:
week()
isoWeek()
Так как они используют разные правила календаря.
function getWeeklyReportId(date) {
return moment(date)
.format('GGGG-[W]WW');
}
console.log(
getWeeklyReportId('2021-01-01')
);
Результат:
2020-W53
const start = moment()
.startOf('isoWeek');
for (let i = 0; i < 7; i++) {
console.log(
start.clone().add(i, 'days').format()
);
}
const dates = [
'2020-12-31',
'2021-01-01',
'2021-01-04'
];
dates.forEach(date => {
const m = moment(date);
console.log({
date,
year: m.year(),
isoYear: m.isoWeekYear(),
isoWeek: m.isoWeek()
});
});
Формат недельного года часто используется в REST API:
{
year: 2025,
week: 12
}
или:
2025-W12
Moment.js позволяет легко формировать такие идентификаторы.
Операции с недельными годами выполняются быстро, однако при массовой обработке данных рекомендуется:
moment;clone() вместо повторного парсинга;Методы недельного года поддерживаются:
| Метод | Назначение |
|---|---|
week() |
локальная неделя |
weeks() |
алиас week |
isoWeek() |
ISO-неделя |
weekYear() |
локальный недельный год |
isoWeekYear() |
ISO-недельный год |
weekday() |
локальный день недели |
isoWeekday() |
ISO-день недели |
weeksInYear() |
недель в локальном году |
isoWeeksInYear() |
ISO-недель в году |