getDaysInMonth для количества дней

Назначение и базовое поведение

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

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

import { getDaysInMonth } from 'date-fns';

getDaysInMonth(new Date(2024, 1, 10)); // 29
getDaysInMonth(new Date(2023, 1, 10)); // 28
getDaysInMonth(new Date(2023, 0, 1));   // 31

Сигнатура функции

getDaysInMonth(date: Date | number): number

Параметр может быть:

  • экземпляром Date
  • timestamp (число миллисекунд)

Возвращаемое значение — число дней в месяце (от 28 до 31).


Принцип вычисления

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

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

Это позволяет корректно учитывать:

  • разные длины месяцев
  • високосные годы
  • переходы между годами (декабрь → январь)

Поведение по месяцам

Январь, март, май, июль, август, октябрь, декабрь

Эти месяцы всегда имеют 31 день.

getDaysInMonth(new Date(2025, 0)); // 31 (январь)
getDaysInMonth(new Date(2025, 6)); // 31 (июль)

Апрель, июнь, сентябрь, ноябрь

Эти месяцы всегда имеют 30 дней.

getDaysInMonth(new Date(2025, 3)); // 30 (апрель)
getDaysInMonth(new Date(2025, 8)); // 30 (сентябрь)

Февраль

Февраль зависит от високосного года:

  • 28 дней в обычном году
  • 29 дней в високосном
getDaysInMonth(new Date(2023, 1)); // 28
getDaysInMonth(new Date(2024, 1)); // 29

Високосный год и его влияние

Високосность определяется стандартными правилами григорианского календаря:

  • год делится на 4 → потенциально високосный
  • не делится на 100 → подтверждение
  • делится на 400 → исключение из правила

Примеры:

  • 2024 — високосный
  • 2100 — не високосный
  • 2000 — високосный

Функция getDaysInMonth не требует ручной проверки этих правил, так как использует встроенную календарную модель JavaScript.


Использование с различными типами входных данных

Передача объекта Date

getDaysInMonth(new Date(2025, 4, 15)); // май → 31

Передача timestamp

getDaysInMonth(Date.now());

Это позволяет работать с данными из API, где даты часто представлены числами.

Преобразование строк дат

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

import { parseISO, getDaysInMonth } from 'date-fns';

getDaysInMonth(parseISO('2025-06-10'));

Практические сценарии применения

Валидация пользовательского ввода

Часто используется для проверки корректности дней месяца:

function isValidDay(year, month, day) {
  const maxDays = getDaysInMonth(new Date(year, month));
  return day >= 1 && day <= maxDays;
}

Построение календарных интерфейсов

При генерации календарной сетки необходимо знать длину месяца:

function generateMonth(year, month) {
  const days = getDaysInMonth(new Date(year, month));
  return Array.from({ length: days }, (_, i) => i + 1);
}

Расчёт диапазонов дат

Используется при формировании периодов:

function getMonthRange(year, month) {
  const start = new Date(year, month, 1);
  const end = new Date(year, month, getDaysInMonth(start));
  return { start, end };
}

Работа с индексами месяцев

Важно учитывать, что в JavaScript и date-fns месяцы нумеруются с нуля:

  • 0 — январь
  • 1 — февраль
  • 11 — декабрь

Это влияет на передаваемые параметры:

new Date(2025, 0); // январь
new Date(2025, 11); // декабрь

Ошибка в индексации может привести к неверным результатам в логике расчёта.


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

Хотя getDaysInMonth работает с датой как с абстракцией календаря, в JavaScript возможны нюансы:

  • Date хранит время в UTC внутри
  • локальная временная зона влияет на отображение
  • но не влияет на количество дней месяца

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


Пограничные случаи

Некорректная дата

getDaysInMonth(new Date('invalid'));

В подобных случаях результат может быть некорректным (часто NaN), так как внутренняя дата становится недействительной.

Переходы между годами

getDaysInMonth(new Date(2025, 11)); // декабрь → 31

Логика корректно обрабатывает декабрь без необходимости дополнительных условий.


Производительность и внутренние оптимизации

Функция выполняет минимальный набор операций:

  • создание двух объектов Date
  • вычисление разницы между ними

Операции имеют константную сложность O(1), поэтому функция подходит для массовых вычислений:

  • генерация календарей
  • обработка больших массивов дат
  • серверные вычисления периодов

Сравнение с ручной реализацией

Без использования библиотеки обычно пишут:

function getDaysInMonthNative(date) {
  const year = date.getFullYear();
  const month = date.getMonth();
  return new Date(year, month + 1, 0).getDate();
}

Вариант из date-fns:

import { getDaysInMonth } from 'date-fns';

Разница заключается в:

  • читаемости
  • унификации API
  • снижении риска ошибок при работе с датами

Интеграция в бизнес-логику

Расчёт зарплаты по дням месяца

function dailyRate(monthlySalary, date) {
  const days = getDaysInMonth(date);
  return monthlySalary / days;
}

Планирование задач

function getMonthlySchedule(year, month) {
  const days = getDaysInMonth(new Date(year, month));
  return new Array(days).fill(null).map((_, i) => ({
    day: i + 1,
    tasks: []
  }));
}

Поведение при изменении даты

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

const d = new Date(2025, 2, 15);
getDaysInMonth(d);

d.getDate(); // остаётся неизменным

Типичные ошибки при использовании

  • передача строки без парсинга
  • путаница с индексами месяцев
  • ожидание влияния временной зоны
  • попытка использовать результат как индекс последнего дня без учёта смещения
// ошибка: строка без парсинга
getDaysInMonth('2025-05-10');

// корректно
getDaysInMonth(parseISO('2025-05-10'));

Поведение в рамках календарной логики

Функция строго следует григорианскому календарю и не учитывает:

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

Это делает её предсказуемой в современных приложениях, где используется стандартная календарная система.