date-fns

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

Установка выполняется через npm или yarn:

npm install dayjs
yarn add dayjs

После подключения создаётся базовый объект даты:

import dayjs from 'dayjs';

const now = dayjs();

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


Создание дат и базовые форматы

Создание даты возможно из различных источников:

dayjs(); // текущая дата
dayjs('2026-01-01'); // строка
dayjs(1672531200000); // timestamp
dayjs(new Date()); // объект Date

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

dayjs().format('YYYY-MM-DD');
dayjs().format('DD.MM.YYYY HH:mm');
dayjs().format('MMMM D, YYYY');

Основные токены:

  • YYYY — год
  • MM — месяц
  • DD — день
  • HH — часы (24h)
  • mm — минуты
  • ss — секунды

Форматирование не изменяет объект, а возвращает строку.


Изменение дат через цепочки вызовов

Операции добавления и вычитания реализованы через add и subtract:

dayjs().add(1, 'day');
dayjs().add(2, 'month');
dayjs().subtract(10, 'year');

Поддерживаемые единицы времени:

  • millisecond
  • second
  • minute
  • hour
  • day
  • week
  • month
  • year

Пример цепочки:

dayjs()
  .add(7, 'day')
  .subtract(2, 'hour')
  .format('YYYY-MM-DD HH:mm');

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


Сравнение дат

Сравнение реализуется через методы isBefore, isAfter, isSame:

dayjs('2026-01-01').isBefore('2026-02-01');
dayjs('2026-01-01').isAfter('2025-12-31');
dayjs('2026-01-01').isSame('2026-01-01');

Можно уточнять единицу сравнения:

dayjs('2026-01-15').isSame('2026-01-20', 'month');

Это позволяет игнорировать более мелкие компоненты даты (например, день при сравнении месяцев).


Работа с компонентами даты

Получение отдельных частей даты:

const d = dayjs();

d.year();
d.month(); // 0–11
d.date();  // день месяца
d.hour();
d.minute();
d.second();

Изменение компонентов:

dayjs().set('year', 2030);
dayjs().set('month', 5);
dayjs().set('date', 10);

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


Таймстемпы и преобразования

Получение timestamp:

dayjs().valueOf(); // миллисекунды
dayjs().unix();    // секунды

Преобразование обратно:

dayjs(1672531200 * 1000);

Работа с Unix-временем особенно важна в API-интеграциях и логировании событий.


Парсинг строк и строгие форматы

Day.js поддерживает парсинг строк, но по умолчанию он не строгий. Для строгого парсинга используется плагин customParseFormat:

import customParseFormat from 'dayjs/plugin/customParseFormat';
dayjs.extend(customParseFormat);

dayjs('01-02-2026', 'DD-MM-YYYY');

Без расширения библиотека может интерпретировать строки менее предсказуемо, полагаясь на встроенный парсер JavaScript.


Расширение функциональности через плагины

Архитектура Day.js построена вокруг плагинов. Базовая библиотека остаётся минимальной, а дополнительные возможности подключаются отдельно.

Пример подключения:

import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';

dayjs.extend(utc);
dayjs.extend(timezone);

Плагины добавляют:

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

Работа с UTC и часовыми поясами

После подключения плагинов:

dayjs().utc().format();
dayjs().tz('Asia/Almaty').format();

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

Пример нормализации:

const utcTime = dayjs().utc();
const localTime = utcTime.local();

Относительное время

Плагин relativeTime добавляет человекочитаемые выражения:

import relativeTime from 'dayjs/plugin/relativeTime';
dayjs.extend(relativeTime);

dayjs().from(dayjs().subtract(2, 'day'));

Результаты:

  • «2 days ago»
  • «in 3 hours»

Локализация поддерживается через подключение языков:

import 'dayjs/locale/ru';
dayjs.locale('ru');

Календарное время

Плагин calendar позволяет отображать даты относительно текущего дня:

import calendar from 'dayjs/plugin/calendar';
dayjs.extend(calendar);

dayjs().calendar();

Вывод формируется в стиле:

  • «Today at 14:00»
  • «Yesterday at 10:30»
  • «Last Monday at 18:00»

Иммутабельность и модель данных

Каждая операция создаёт новый объект:

const a = dayjs();
const b = a.add(1, 'day');

a.format('YYYY-MM-DD');
b.format('YYYY-MM-DD');

a остаётся неизменным, что упрощает работу в функциональных и реактивных архитектурах (React, Vue, state management системы).


Сравнение с date-fns

Библиотека date-fns использует иной подход: вместо цепочек методов применяется набор чистых функций.

Пример:

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

format(addDays(new Date(), 1), 'yyyy-MM-dd');

Различия:

  • Day.js — объектная модель с цепочками
  • date-fns — функциональный стиль без состояния
  • Day.js — плагины расширяют объект
  • date-fns — tree-shaking на уровне функций

Day.js чаще выбирается при необходимости компактного API и привычной объектной работы с датами.


Работа с валидностью дат

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

dayjs('invalid-date').isValid();

Метод возвращает false для некорректных значений, что позволяет безопасно обрабатывать пользовательский ввод.


Клонирование и безопасность операций

Каждая трансформация уже является клоном, но явное клонирование возможно:

const d = dayjs();
const copy = d.clone();

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


Арифметика дат и пограничные случаи

При работе с месяцами и годами возникают особенности календаря:

dayjs('2026-01-31').add(1, 'month');

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


Оптимизация и размер библиотеки

Одним из ключевых преимуществ Day.js является минимальный размер ядра — около нескольких килобайт. Это достигается за счёт:

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

Это делает библиотеку применимой в клиентских приложениях с жёсткими ограничениями по бандлу.


Интероперабельность с JavaScript Date

Преобразование обратно в стандартный объект:

dayjs().toDate();

Это позволяет использовать Day.js как слой абстракции поверх встроенной системы времени, не нарушая совместимость с API браузера и Node.js.