Отличия в API

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

Ключевая особенность:

  • отсутствие состояния внутри библиотеки
  • отсутствие классов и экземпляров дат
  • каждая функция работает как чистая трансформация данных

Такой подход делает API предсказуемым и хорошо совместимым с современными инструментами сборки.


Модульность и точечные импорты

Одно из принципиальных отличий API date-fns — модульная структура. Каждая функция существует как отдельный модуль:

import format from 'date-fns/format'
import addDays from 'date-fns/addDays'

Такой стиль импорта приводит к важным особенностям:

  • поддержка tree-shaking на уровне сборщиков
  • отсутствие необходимости подключать библиотеку целиком
  • минимизация конечного бандла

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


Позиционный стиль аргументов

Функции date-fns используют строго определённый порядок аргументов:

  1. основная дата
  2. параметры операции
  3. объект опций (если требуется)

Пример:

format(new Date(), 'yyyy-MM-dd')

или

addDays(new Date(), 5)

Особенности такого подхода:

  • отсутствие перегруженных сигнатур
  • единообразие во всех функциях
  • предсказуемость порядка аргументов

Дополнительные настройки почти всегда передаются последним аргументом:

format(new Date(), 'PPP', { locale: ru })

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

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

Пример поведения:

const date = new Date()
const newDate = addDays(date, 3)

После выполнения:

  • date остаётся неизменной
  • newDate содержит результат вычисления

Это отличается от библиотек, где методы могут мутировать исходный объект. В API date-fns это исключено на уровне дизайна.


Отсутствие расширения прототипа Date

Date-fns не модифицирует глобальный объект Date и не добавляет методы в его прототип.

Это означает:

  • нет Date.prototype.format
  • нет Date.prototype.addDays
  • все операции выполняются только через функции библиотеки

Такое решение устраняет конфликты с другими библиотеками и снижает риск неожиданных изменений поведения стандартного объекта.


Разделение на основной API и FP API

В date-fns существует два подхода к использованию функций:

Основной API

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

import add from 'date-fns/add'
add(new Date(), { days: 2 })

FP-версия API

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

import { add } from 'date-fns/fp'
const addTwoDays = add({ days: 2 })
addTwoDays(new Date())

Отличия FP-API:

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

Различия в структуре параметров между версиями API

Некоторые функции имеют разные сигнатуры в зависимости от версии API.

Основной API:

format(date, formatString, options)

FP API:

format(formatString, options)(date)

Это создаёт два разных стиля работы:

  • императивный (основной API)
  • функционально-композиционный (FP API)

Локализация как часть API

Поддержка локалей реализована через явную передачу объекта локали:

import { ru } from 'date-fns/locale'
format(new Date(), 'PPP', { locale: ru })

Отличия API в работе с локалями:

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

Такой подход исключает глобальное состояние и делает локализацию изолированной.


Различия между версиями API (v1, v2, v3)

Эволюция date-fns сопровождалась изменениями в API.

Переход от v1 к v2

Основные изменения:

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

Переход к v3

  • улучшение совместимости с ESM
  • более строгая типизация (в TypeScript-окружениях)
  • оптимизация tree-shaking

Различия в подходе к ошибкам

API date-fns придерживается строгой модели:

  • некорректные значения приводят к Invalid Date
  • отсутствует скрытая обработка ошибок
  • нет подавления исключений внутри функций

Пример поведения:

format(new Date('invalid'), 'yyyy-MM-dd')
// Invalid Date

Такой подход отличается от библиотек, где ошибки могут обрабатываться внутри и заменяться fallback-значениями.


Единообразие API между функциями

Несмотря на большое количество функций, API сохраняет структурную консистентность:

  • функция = одно действие
  • вход: Date или timestamp
  • выход: новый Date или строка
  • опции всегда последним параметром

Примеры:

addMonths(date, 1)
subDays(date, 10)
differenceInDays(dateLeft, dateRight)

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


Отличия от объектно-ориентированных API

В отличие от OOP-библиотек:

  • нет цепочек вызовов date.add().format()
  • нет состояния объекта
  • нет методов экземпляра

Каждая операция — это самостоятельная функция:

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

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


Стабильность сигнатур и обратная совместимость

API date-fns ориентирован на стабильность:

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

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