Операции с кварталами

В стандартной конфигурации Day.js не оперирует понятием квартала как самостоятельной единицы. Для работы с кварталами используется плагин:

import dayjs from 'dayjs'
import quarterOfYear from 'dayjs/plugin/quarterOfYear'

dayjs.extend(quarterOfYear)

После подключения расширения становится доступен набор методов, позволяющих рассматривать дату в терминах кварталов финансового или календарного года.

Квартал определяется как трёхмесячный интервал:

  • Q1: январь — март
  • Q2: апрель — июнь
  • Q3: июль — сентябрь
  • Q4: октябрь — декабрь

Получение квартала из даты

Метод quarter() возвращает номер квартала (от 1 до 4):

dayjs('2026-02-10').quarter() // 1
dayjs('2026-05-10').quarter() // 2
dayjs('2026-11-10').quarter() // 4

Поведение основано на месяце даты:

const month = dayjs(date).month() // 0–11

// логика квартала:
Math.floor(month / 3) + 1

Квартал всегда вычисляется относительно стандартного календарного года.


Установка квартала

Метод quarter(value) позволяет изменить квартал, сохраняя год и день в пределах допустимого диапазона:

dayjs('2026-01-15').quarter(3).format() 
// 2026-07-15...

При установке:

  • месяц пересчитывается автоматически
  • день сохраняется, если он существует в новом месяце
  • при конфликте дат происходит нормализация (например, 31 число может стать 30 или 28)

Примеры:

dayjs('2026-01-31').quarter(2).format()
// 2026-04-30 (или ближайшая корректная дата)

Начало квартала

Метод startOf('quarter') возвращает первый день первого месяца квартала:

dayjs('2026-05-17').startOf('quarter').format()
// 2026-04-01 00:00:00

Правила вычисления:

  • определяется текущий квартал
  • месяц округляется вниз до ближайшего кратного 3
  • день устанавливается в 1
  • время сбрасывается до начала суток

Конец квартала

Метод endOf('quarter') возвращает последний момент последнего дня квартала:

dayjs('2026-05-17').endOf('quarter').format()
// 2026-06-30 23:59:59.999

Особенности:

  • учитывается длина месяца (30/31/28/29 дней)
  • время устанавливается в максимально возможное значение суток
  • результат всегда соответствует последней миллисекунде квартала

Сдвиг даты по кварталам

После подключения плагина квартал может использоваться в арифметике:

dayjs('2026-01-10').add(1, 'quarter').format()
// 2026-04-10

dayjs('2026-10-10').subtract(2, 'quarter').format()
// 2026-04-10

Правила вычислений:

  • 1 квартал = 3 месяца
  • операция выполняется через календарную модель, а не фиксированные дни
  • корректируется день месяца при переполнении

Разница между датами в кварталах

Операция diff позволяет вычислить количество кварталов между датами:

dayjs('2026-10-01').diff('2026-01-01', 'quarter')
// 3

Поведение:

  • результат — целое число кварталов
  • дробная часть отбрасывается
  • направление учитывается (положительное или отрицательное значение)
dayjs('2026-01-01').diff('2026-10-01', 'quarter')
// -3

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

Квартальная модель часто применяется в финансовых и аналитических системах.

Разбиение периода на кварталы

function getQuartersBetween(start, end) {
  const result = []
  let cursor = dayjs(start).startOf('quarter')

  while (cursor.isBefore(end)) {
    result.push({
      start: cursor.format(),
      end: cursor.endOf('quarter').format()
    })
    cursor = cursor.add(1, 'quarter')
  }

  return result
}

Проверка принадлежности к кварталу

function isSameQuarter(a, b) {
  return dayjs(a).quarter() === dayjs(b).quarter() &&
         dayjs(a).year() === dayjs(b).year()
}

Построение финансового года с произвольным стартом

Если финансовый год начинается не с января, кварталы можно переопределить логически:

function financialQuarter(date, startMonth = 3) {
  const m = dayjs(date).month()
  const shifted = (m - startMonth + 12) % 12
  return Math.floor(shifted / 3) + 1
}

Сортировка и группировка по кварталам

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

const grouped = {}

transactions.forEach(t => {
  const key = `${dayjs(t.date).year()}-Q${dayjs(t.date).quarter()}`

  if (!grouped[key]) grouped[key] = []
  grouped[key].push(t)
})

Результат:

  • ключи вида 2026-Q1, 2026-Q2
  • структура подходит для отчетности и графиков

Особенности нормализации дат при работе с кварталами

При изменении квартала или добавлении нескольких кварталов возможны корректировки:

  • даты с 29–31 числом могут сдвигаться
  • переход между месяцами учитывает длину каждого месяца
  • временная зона влияет на итоговую метку времени
dayjs('2026-01-31').add(1, 'quarter')
// может стать 2026-04-30

Сравнение кварталов как временных интервалов

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

function compareQuarters(a, b) {
  const qa = dayjs(a)
  const qb = dayjs(b)

  const diffYear = qa.year() - qb.year()
  if (diffYear !== 0) return diffYear

  return qa.quarter() - qb.quarter()
}

Формирование отчетных периодов

Кварталы часто используются для формирования отчетных диапазонов:

function getQuarterRange(date) {
  const d = dayjs(date)

  return {
    start: d.startOf('quarter'),
    end: d.endOf('quarter'),
    label: `Q${d.quarter()} ${d.year()}`
  }
}

Структура результата позволяет напрямую использовать диапазон в запросах к базам данных или API.