Клонирование объектов даты

Экземпляр Day.js представляет собой обёртку над внутренним представлением даты, при этом сам объект проектировался как неизменяемый. Любая операция преобразования времени — добавление дней, изменение месяца, форматирование — не изменяет исходный экземпляр, а возвращает новый.

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


Базовый принцип неизменяемости

Каждая операция над экземпляром Day.js возвращает новый объект:

import dayjs from "dayjs";

const base = dayjs("2026-01-01");

const updated = base.add(7, "day");

console.log(base.format());     // 2026-01-01
console.log(updated.format());  // 2026-01-08

Исходный объект base остаётся неизменным, что уже является формой автоматического “безопасного клонирования” при трансформациях.


Создание копии через повторное оборачивание

Наиболее простой способ получить независимый экземпляр — передать существующий объект Day.js в конструктор:

const original = dayjs("2026-05-10");
const copy = dayjs(original);

Такой подход создаёт новый экземпляр, полностью отделённый от исходного. Это особенно полезно, когда требуется гарантировать, что дальнейшие операции не будут логически связаны с предыдущей цепочкой вычислений.


Метод clone()

В Day.js предусмотрен явный метод клонирования:

const original = dayjs("2026-05-10");
const copy = original.clone();

Поведение метода идентично повторной инициализации через dayjs(original), но синтаксически он более выразителен и подчёркивает намерение разработчика — именно клонирование, а не преобразование.


Важное отличие: объект Day.js и native Date

Несмотря на удобство Day.js, внутри часто возникает необходимость взаимодействия с нативным объектом JavaScript Date. Метод .toDate() возвращает обычный объект Date:

const d = dayjs("2026-05-10");
const native = d.toDate();

Здесь появляется принципиально иная семантика: Date является изменяемым объектом. Любое изменение затронет именно этот экземпляр:

native.setDate(1);

При этом сам Day.js объект остаётся неизменным, так как связь односторонняя.


Клонирование через toDate() и обратную обёртку

Если требуется получить независимую копию, включающую native Date, используется двойное преобразование:

const original = dayjs("2026-05-10");

const clone = dayjs(original.toDate());

В этом случае создаётся новый экземпляр Day.js, основанный на новом объекте Date, что разрывает все возможные ссылки на исходные данные.


Ошибочные подходы к клонированию

Присваивание переменной

const a = dayjs("2026-01-01");
const b = a;

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


Использование spread-оператора

const copy = { ...dayjs("2026-01-01") };

Такой подход не создаёт корректный экземпляр Day.js. В результате получается обычный объект с внутренними полями библиотеки, но без методов прототипа.


JSON-сериализация

const copy = dayjs(JSON.parse(JSON.stringify(dayjs("2026-01-01"))));

Подобный способ избыточен и может привести к потере информации о временной зоне и внутренних расширениях плагинов. Day.js не требует такого подхода.


Клонирование в цепочках вызовов

Одно из типичных применений клонирования возникает при сохранении промежуточного состояния в цепочке преобразований:

const base = dayjs("2026-05-10");

const snapshot = base.clone();

const result = base.add(3, "day").subtract(1, "month");

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


Поведение с плагинами и расширениями

Некоторые плагины Day.js добавляют новые методы или изменяют поведение экземпляров. Клонирование через .clone() сохраняет все подключённые плагины и их расширения, поскольку новый объект создаётся на основе внутреннего состояния текущего экземпляра.

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


Практика безопасного копирования

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

const copy1 = dayjs(original);
const copy2 = original.clone();

Первый вариант предпочтителен при создании нового экземпляра из внешнего значения, второй — при явном клонировании уже существующего объекта в рамках логики.


Взаимодействие клонирования и форматирования

Клонирование не влияет на форматирование, так как форматирование не изменяет объект:

const a = dayjs("2026-05-10");
const b = a.clone();

console.log(a.format("YYYY-MM-DD"));
console.log(b.format("YYYY-MM-DD"));

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


Клонирование и производительность

Создание копий Day.js объектов дешево по ресурсам. Библиотека оптимизирована под частые операции создания новых экземпляров, поэтому использование .clone() не требует специальных оптимизаций или кеширования на уровне приложения.

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