Библиотека date-fns

date-fns — модульная JavaScript-библиотека для работы с датами. Она предоставляет функцию formatDistanceToNow и родственные функции для получения относительного времени, которые можно использовать вместо timeago.js.


Установка и базовое использование

npm install date-fns
import { formatDistanceToNow, formatDistance } from 'date-fns';
import { ru } from 'date-fns/locale';

// Расстояние от текущего момента
formatDistanceToNow(new Date('2025-05-31'), { locale: ru });
// "около 1 суток"

// С суффиксом
formatDistanceToNow(new Date('2025-05-31'), { locale: ru, addSuffix: true });
// "около 1 суток назад"

// Расстояние между двумя датами
formatDistance(new Date('2025-01-01'), new Date('2025-06-01'), { locale: ru, addSuffix: true });
// "около 5 месяцев назад"

Сравнение API

Функция timeago.js date-fns
Относительное время format(date, 'ru') formatDistanceToNow(date, { locale: ru, addSuffix: true })
Кастомная база format(date, 'ru', { relativeDate }) formatDistance(date, baseDate, { locale: ru })
Авторендер render(el) + cancel(el) Нет — самостоятельно через setInterval
Локали register(code, fn) Импорт из date-fns/locale

Форматы вывода

import { formatDistanceToNow } from 'date-fns';
import { ru } from 'date-fns/locale';

const date = new Date(Date.now() - 5 * 60_000);

// Без суффикса
formatDistanceToNow(date, { locale: ru });           // "5 минут"

// С суффиксом (добавляет "назад" / "через")
formatDistanceToNow(date, { locale: ru, addSuffix: true }); // "5 минут назад"

// Строгий режим (без "около", "меньше")
formatDistanceToNow(date, { locale: ru, includeSeconds: true }); // "5 минут"

Поддерживаемые локали

date-fns предоставляет более 100 локалей:

import { ru }    from 'date-fns/locale';
import { de }    from 'date-fns/locale';
import { zhCN }  from 'date-fns/locale';
import { ar }    from 'date-fns/locale';
import { ja }    from 'date-fns/locale';

formatDistanceToNow(date, { locale: de, addSuffix: true });  // "vor 5 Minuten"
formatDistanceToNow(date, { locale: ja, addSuffix: true });  // "5分前"

Автообновление DOM с date-fns

import { formatDistanceToNow } from 'date-fns';
import { ru } from 'date-fns/locale';

function startUpdates(selector = '[datetime]') {
  const elements = document.querySelectorAll(selector);

  function update() {
    elements.forEach(el => {
      const datetime = el.getAttribute('datetime');
      if (!datetime) return;
      const next = formatDistanceToNow(new Date(datetime), { locale: ru, addSuffix: true });
      if (el.textContent !== next) el.textContent = next;
    });
  }

  update();
  const id = setInterval(update, 30_000);
  return () => clearInterval(id);
}

React хук с date-fns

import { useState, useEffect } from 'react';
import { formatDistanceToNow } from 'date-fns';
import { ru } from 'date-fns/locale';

function useDateFnsTimeAgo(date: Date | string) {
  const getLabel = () =>
    formatDistanceToNow(new Date(date), { locale: ru, addSuffix: true });

  const [label, setLabel] = useState(getLabel);

  useEffect(() => {
    const id = setInterval(() => setLabel(getLabel()), 30_000);
    return () => clearInterval(id);
  }, [date]);

  return label;
}

Отличия в формулировках

import { format as timeagoFormat } from 'timeago.js';
import { formatDistanceToNow } from 'date-fns';
import { ru } from 'date-fns/locale';

const fiveMinAgo = new Date(Date.now() - 5 * 60_000);

timeagoFormat(fiveMinAgo, 'ru');
// "5 минут назад"

formatDistanceToNow(fiveMinAgo, { locale: ru, addSuffix: true });
// "5 минут назад"

// Разница для коротких интервалов:
const thirtySecAgo = new Date(Date.now() - 30_000);
timeagoFormat(thirtySecAgo, 'ru');
// "только что"

formatDistanceToNow(thirtySecAgo, { locale: ru, addSuffix: true });
// "меньше минуты назад"

Треешейкинг

date-fns полностью модульна — импортируется только то, что используется:

// Только formatDistanceToNow и локаль ru — остальное не попадает в бандл
import { formatDistanceToNow } from 'date-fns/formatDistanceToNow';
import { ru } from 'date-fns/locale/ru';

Размер бандла

Библиотека Основной пакет Одна локаль
timeago.js ~2 KB gzip ~0.5 KB
date-fns (RTF) ~5 KB gzip ~2 KB
Intl.RTF 0 — нативный 0

Когда date-fns предпочтительнее timeago.js

  • В проекте уже используется date-fns для других операций с датами.
  • Нужны функции вроде format, addDays, isBefore — не только относительное время.
  • Необходима строгая типизация без кастомных .d.ts.
  • Формулировки “меньше минуты” / “около 1 часа” лучше подходят для продукта.