Установка компонентов даты: set, setYear, setMonth

Библиотека date-fns предоставляет набор чистых функций для работы с датами в JavaScript без мутаций исходных объектов Date. Одной из ключевых групп функций являются операции установки компонентов даты, позволяющие изменять год, месяц, день и другие части времени в иммутабельном стиле.


Все функции установки в date-fns возвращают новый объект Date, не изменяя исходный. Это важное отличие от нативных методов JavaScript, таких как setFullYear, setMonth и других, которые мутируют объект.

Основные последствия такого подхода:

  • предсказуемость поведения
  • отсутствие скрытых побочных эффектов
  • удобство в функциональном стиле
  • безопасность при работе с состоянием (например, в React, Redux)

set — универсальная установка компонентов даты

Функция set позволяет одновременно изменить несколько частей даты за один вызов.

Сигнатура

set(date, values)
  • date — исходный объект Date
  • values — объект с полями для изменения

Поддерживаемые поля:

  • year
  • month (0–11)
  • date (день месяца)
  • hours
  • minutes
  • seconds
  • milliseconds

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

import { set } from "date-fns";

const baseDate = new Date(2024, 5, 10, 12, 30);

const upd ated = se t(baseDate, {
  year: 2025,
  month: 0,
  date: 1
});

console.log(upd ated);
// 1 января 2025, 12:30

Исходная дата остаётся неизменной:

console.log(baseDate);
// 10 июня 2024, 12:30

Частичное обновление времени

const date = new Date(2024, 5, 10, 12, 30, 45);

const result = se t(date, {
  hours: 0,
  minutes: 0,
  seconds: 0
});

console.log(result);
// 10 июня 2024, 00:00:00

Особенности поведения set

  1. Нормализация значений Если передать выходящие за диапазон значения, они будут корректно перенесены:
set(new Date(2024, 0, 31), { month: 1, date: 40 });
// корректно пересчитает дату с переносом в следующий месяц
  1. Локальное время Все операции выполняются в локальном часовом поясе среды выполнения.

  2. Порядок применения Значения применяются одновременно, что исключает промежуточные состояния.


setYear — изменение только года

Функция setYear предназначена для точечного изменения года без необходимости указывать другие компоненты даты.

Сигнатура

setYear(date, year)

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

import { setYear } from "date-fns";

const date = new Date(2020, 5, 15);

const upd ated = setYear(date, 2026);

console.log(upd ated);
// 15 июня 2026

Поведение при граничных датах

Особенность работы с 29 февраля:

const leapDate = new Date(2020, 1, 29);

const result = setYear(leapDate, 2021);

console.log(result);
// 1 марта 2021 (или 28 февраля в зависимости от нормализации среды)

Это связано с тем, что 29 февраля не существует в невисокосный год, и JavaScript автоматически корректирует дату.


Отличие от se t

set(date, { year: 2025 })
setYear(date, 2025)

Функционально результаты схожи, но:

  • setYear — более узкая и читаемая операция
  • set — универсальный инструмент для нескольких полей одновременно

setMonth — изменение месяца

Функция setMonth изменяет месяц даты, сохраняя остальные компоненты.

Сигнатура

setMonth(date, month)
  • month — число от 0 до 11

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

import { setMonth } from "date-fns";

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

const upd ated = setMonth(date, 5);

console.log(upd ated);
// 15 июня 2024

Важный момент: нумерация месяцев

В JavaScript и date-fns:

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

Это часто является источником ошибок при работе с датами.


Переполнение дней месяца

Если текущий день не существует в новом месяце, происходит автоматическая корректировка:

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

const upd ated = setMonth(date, 1);

console.log(upd ated);
// 2 марта 2024 (или 29 февраля в високосный год)

Причина — февраль не имеет 31 дня, поэтому дата «перепрыгивает» в следующий месяц.


Использование в цепочках преобразований

import { setMonth, setYear } from "date-fns";

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

const result = setYear(setMonth(date, 11), 2025);

console.log(result);
// 10 декабря 2025

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


Сравнение se t, setYear и setMonth

Область применения

  • set — комплексное изменение нескольких компонентов
  • setYear — изменение только года
  • setMonth — изменение только месяца

Читаемость кода

set(date, { year: 2025, month: 6 })

vs

setMonth(setYear(date, 2025), 6)

Первый вариант:

  • компактнее
  • удобнее для массовых изменений

Второй вариант:

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

Производительность

Разница минимальна, но:

  • set выполняет одну операцию
  • комбинации setYear + setMonth создают несколько промежуточных объектов Date

Работа с краевыми случаями

Переполнение значений

Все функции используют внутреннюю нормализацию Jav * aScript:

  • выход за пределы месяцев переносит дату
  • отрицательные значения также корректируются
setMonth(new Date(2024, 0, 15), -1);
// декабрь предыдущего года

Несуществующие даты

set(new Date(2024, 0, 31), { month: 1, date: 31 });

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


Изменение високосных дат

setYear(new Date(2020, 1, 29), 2024);

Дата остаётся корректной, так как 2024 — високосный год.


Практические сценарии использования

Формирование даты события в будущем

const base = new Date();

const eventDate = se t(base, {
  year: 2027,
  month: 8,
  date: 1
});

Сброс месяца при смене года

const reset = setYear(new Date(), 2030);
const january = setMonth(reset, 0);

Генерация даты начала периода

const periodStart = se t(new Date(), {
  date: 1,
  hours: 0,
  minutes: 0,
  seconds: 0,
  milliseconds: 0
});

Использование в календарных интерфейсах

При переключении месяцев в UI часто используется setMonth:

function nextMonth(date) {
  return setMonth(date, date.getMonth() + 1);
}

Взаимодействие с другими функциями date-fns

Функции установки часто комбинируются с:

  • add / sub — арифметика дат
  • startOfMonth, startOfYear — нормализация границ
  • format — вывод результата

Пример:

import { setMonth, startOfMonth, format } from "date-fns";

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

const next = startOfMonth(setMonth(date, 5));

console.log(format(next, "yyyy-MM-dd"));
// 2024-06-01

Архитектурные особенности подхода date-fns

Функции set, setYear, setMonth реализованы в едином стиле:

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

Это делает библиотеку удобной для:

  • фронтенд-приложений
  • серверных вычислений (Node.js)
  • тестируемых функциональных систем

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

1. Путаница индексации месяцев

setMonth(date, 6); // июль, а не июнь

2. Ожидание мутации объекта

setMonth(date, 5);
console.log(date); // старая дата, без изменений

3. Неверная комбинация setYear и setMonth

setYear(setMonth(date, 1), 2025);

Важно учитывать, что каждый вызов создаёт новый объект.


Поведение в цепочках преобразований

const result = setMonth(
  setYear(
    set(new Date(), { date: 10 }),
    2035
  ),
  9
);

Каждый уровень возвращает новый Date, формируя чистую цепочку преобразований без побочных эффектов.