Добавление и вычитание кварталов

Квартал в календарном представлении представляет собой фиксированный трехмесячный интервал, используемый при финансовых расчетах, отчетности и временной агрегации данных. В библиотеке Date-fns работа с кварталами реализована через операции с календарными единицами, где квартал трактуется как строго 3 месяца, начиная с текущей позиции даты.

Основной набор функций включает добавление и вычитание кварталов, что позволяет изменять дату с сохранением календарной структуры без ручного пересчета месяцев.


Квартал определяется как:

  • 1 квартал = 3 месяца
  • 2 квартала = 6 месяцев
  • 3 квартала = 9 месяцев
  • 4 квартала = 12 месяцев

При вычислениях используется календарная арифметика, а не фиксированное количество дней. Это означает, что переход между кварталами учитывает различную длину месяцев (28–31 день), а также високосные годы.


Добавление кварталов

Для увеличения даты на определенное количество кварталов используется функция addQuarters.

Сигнатура:

addQuarters(date, amount)

Где:

  • date — исходная дата
  • amount — количество кварталов для добавления

Функция возвращает новый объект Date, не изменяя исходную дату, что соответствует принципу неизменяемости.

Пример базового использования

import { addQuarters } from 'date-fns';

const date = new Date(2024, 0, 15); // 15 января 2024

const result = addQuarters(date, 1);
// 15 апреля 2024

Добавление одного квартала эквивалентно увеличению месяца на 3.


Добавление нескольких кварталов

import { addQuarters } from 'date-fns';

const date = new Date(2024, 2, 10); // 10 марта 2024

const result = addQuarters(date, 2);
// 10 сентября 2024

Здесь происходит переход через два календарных квартала: март → июнь → сентябрь.


Особенности поведения при переходе месяцев

При добавлении кварталов сохраняется день месяца, если это возможно. В ситуациях, когда целевой месяц имеет меньше дней, происходит корректировка:

import { addQuarters } from 'date-fns';

const date = new Date(2024, 0, 31); // 31 января

const result = addQuarters(date, 1);
// 30 апреля (или 1 мая в зависимости от пересчета календаря)

Такое поведение связано с тем, что апрель имеет 30 дней.


Вычитание кварталов

Операция обратного смещения реализуется функцией subQuarters.

Сигнатура:

subQuarters(date, amount)

Где:

  • date — исходная дата
  • amount — количество кварталов для вычитания

Пример базового использования

import { subQuarters } from 'date-fns';

const date = new Date(2024, 9, 20); // 20 октября 2024

const result = subQuarters(date, 1);
// 20 июля 2024

Вычитание нескольких кварталов

import { subQuarters } from 'date-fns';

const date = new Date(2024, 11, 1); // 1 декабря 2024

const result = subQuarters(date, 3);
// 1 марта 2024

Происходит последовательное смещение назад по трехмесячным интервалам.


Календарная природа операций

Обе функции работают на основе календарной модели:

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

Это отличает квартальные операции от низкоуровневых арифметических вычислений с таймстампами.


Поведение на границах кварталов

Кварталы традиционно распределяются следующим образом:

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

При добавлении кварталов переход происходит между этими блоками, однако сама функция не оперирует понятием «Q1–Q4», а работает через смещение месяцев.

import { addQuarters } from 'date-fns';

const date = new Date(2024, 11, 31); // 31 декабря 2024

const result = addQuarters(date, 1);
// март 2025 (дата корректируется внутри месяца)

Сочетание с другими операциями даты

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

Добавление кварталов и дней

import { addQuarters, addDays } from 'date-fns';

const base = new Date(2024, 0, 1);

const result = addDays(addQuarters(base, 1), 10);

Сначала происходит смещение на квартал, затем добавляются дни.


Вычитание кварталов и нормализация даты

import { subQuarters, startOfMonth } from 'date-fns';

const date = new Date(2024, 6, 15);

const result = startOfMonth(subQuarters(date, 2));

Сначала дата смещается назад на два квартала, затем нормализуется к началу месяца.


Иммутабельность и побочные эффекты

Операции добавления и вычитания кварталов не модифицируют исходную дату. Это позволяет безопасно использовать их в цепочках преобразований и функциональных композициях.

const original = new Date(2024, 3, 10);

const shifted = addQuarters(original, 2);

original === shifted; // false

Типичные сценарии применения

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

  • расчете финансовых периодов отчетности
  • планировании релизов по кварталам
  • агрегации аналитических данных
  • построении временных диапазонов в BI-системах

Особенности работы с високосными годами

Так как квартал основан на месяцах, високосный год влияет только на длину февраля:

const date = new Date(2024, 0, 31);

const result = addQuarters(date, 1);

Февраль 2024 содержит 29 дней, что влияет на итоговую корректировку при переносе дат на конец месяца.


Поведение при отрицательных значениях

Хотя основная логика разделена на add/sub функции, передача отрицательных значений в addQuarters приводит к эквиваленту вычитания и наоборот:

addQuarters(date, -1); // эквивалент subQuarters(date, 1)

Однако для читаемости кода обычно используется явная форма.


Цепочки преобразований

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

import { addQuarters, setDate } from 'date-fns';

const date = new Date(2024, 0, 1);

const result = setDate(addQuarters(date, 1), 15);

Сначала дата переносится на следующий квартал, затем устанавливается конкретный день месяца.


Работа с временными зонами

Квартальные операции работают на уровне локального времени объекта Date. Это означает:

  • смещение не учитывает временные зоны напрямую
  • результат зависит от локального представления даты
  • при DST переходах сохраняется логика календарного смещения, а не фиксированных часов