В календарной модели квартал представляет собой период из трёх
месяцев, используемый для финансовой отчётности, аналитики и агрегации
данных. В Moment.js работа с кварталами встроена в систему манипуляции
датами и опирается на методы startOf, endOf и
quarter.
Квартал в Moment.js определяется относительно стандартного календаря:
Moment.js позволяет получить или установить квартал с помощью метода
quarter().
const m = moment('2024-05-17');
m.quarter(); // 2
Значение возвращается в диапазоне от 1 до
4.
Установка квартала изменяет дату, сохраняя день в пределах допустимого диапазона месяца:
const m = moment('2024-01-10');
m.quarter(3);
m.format('YYYY-MM-DD'); // 2024-07-10
При установке квартала библиотека автоматически переводит дату в соответствующий диапазон месяцев (в данном случае — июль, как начало III квартала).
Для получения первого момента квартала используется
startOf('quarter').
const m = moment('2024-08-15');
const start = m.startOf('quarter');
start.format('YYYY-MM-DD HH:mm:ss'); // 2024-07-01 00:00:00
Метод изменяет исходный объект Moment, переводя его в начало квартала:
00:00:00.000Особенность работы заключается в мутации объекта:
const m = moment('2024-08-15');
const start = m.startOf('quarter');
m === start; // true
Если требуется сохранить исходную дату, используется клонирование:
const m = moment('2024-08-15');
const start = m.clone().startOf('quarter');
Метод endOf('quarter') переводит дату в последний момент
квартала.
const m = moment('2024-02-10');
const end = m.endOf('quarter');
end.format('YYYY-MM-DD HH:mm:ss'); // 2024-03-31 23:59:59
Поведение включает:
23:59:59.999Это важно для корректных сравнений диапазонов:
const m = moment('2024-03-31');
m.isSame(moment('2024-03-31').endOf('quarter')); // true
Часто квартал используется как временной диапазон для фильтрации данных.
const m = moment('2024-11-12');
const start = m.clone().startOf('quarter');
const end = m.clone().endOf('quarter');
console.log(start.format('YYYY-MM-DD'));
console.log(end.format('YYYY-MM-DD'));
Результат:
Такой подход применяется при построении запросов к базе данных:
const start = moment().quarter(4).startOf('quarter');
const end = moment().quarter(4).endOf('quarter');
db.query({
createdAt: {
$gte: start.toDate(),
$lte: end.toDate()
}
});
Moment.js вычисляет квартал на основе месяца:
quarter = Math.floor(month / 3) + 1
где month — индекс месяца от 0 до 11.
Соответствие:
Это объясняет поведение метода quarter() при установке
значений: библиотека пересчитывает месяц, исходя из номера квартала и
текущего месяца внутри квартала.
Методы startOf и endOf изменяют исходный
объект. Это критично при цепочках вычислений:
const m = moment('2024-06-15');
const start = m.startOf('quarter');
const end = m.endOf('quarter');
console.log(m.format('YYYY-MM-DD')); // 2024-06-30
После вызова startOf('quarter') дата становится началом
квартала, а последующий endOf('quarter') продолжает
трансформацию уже изменённого объекта.
Корректный подход:
const m = moment('2024-06-15');
const start = m.clone().startOf('quarter');
const end = m.clone().endOf('quarter');
При использовании UTC-режима расчёт кварталов происходит без учёта локальной временной зоны:
const m = moment.utc('2024-10-10');
const start = m.clone().startOf('quarter');
const end = m.clone().endOf('quarter');
Разница между moment() и moment.utc()
проявляется в смещениях дат при переходах через границы суток в
локальных зонах, но сам квартал остаётся календарно идентичным.
Кварталы часто используются для агрегирования метрик:
const now = moment();
const ranges = [];
for (let i = 0; i < 4; i++) {
const start = now.clone().quarter(i + 1).startOf('quarter');
const end = now.clone().quarter(i + 1).endOf('quarter');
ranges.push({
quarter: i + 1,
start: start.toISOString(),
end: end.toISOString()
});
}
Такой подход позволяет формировать отчётные периоды за год.
Проверка принадлежности даты текущему кварталу:
const date = moment('2024-05-20');
const start = moment(date).startOf('quarter');
const end = moment(date).endOf('quarter');
date.isBetween(start, end, null, '[]'); // true
Ключевой момент — включение границ диапазона через '[]',
что важно для точной финансовой отчётности.
Moment.js не поддерживает произвольные финансовые кварталы без
дополнительных решений. Если финансовый год начинается, например, с
апреля, стандартная логика quarter() становится
неприменимой напрямую.
В таких случаях используется ручная нормализация:
function getFiscalQuarter(date) {
const month = date.month(); // 0-11
return Math.floor(((month + 9) % 12) / 3) + 1;
}
Для границ квартала также требуется явное вычисление:
function startOfFiscalQuarter(date) {
const quarter = getFiscalQuarter(date);
const fiscalStartMonth = ((quarter - 1) * 3 + 3) % 12;
return moment(date)
.month(fiscalStartMonth)
.startOf('month');
}
Полученные даты часто приводятся к строковому виду для API:
const start = moment().startOf('quarter').format('YYYY-MM-DD');
const end = moment().endOf('quarter').format('YYYY-MM-DD');
Форматирование зависит от требований системы, но чаще используется ISO-формат или дата без времени.
Определение разницы в кварталах:
const a = moment('2024-01-15');
const b = moment('2024-10-10');
b.diff(a, 'quarters'); // 3
Метод diff позволяет работать с квартальной шкалой как с
единицей измерения времени.