Служебные методы

Помимо основных функций (format, render, cancel, register), в timeago.js есть внутренние механизмы, которые можно использовать через обёртки или изучить для создания расширений.


Публичное API библиотеки

Официальный публичный API timeago.js:

Метод Назначение
format Форматирование даты в строку
render Автообновление DOM-элементов
cancel Остановка автообновлений
register Регистрация локали

Служебных методов в публичном API нет. Все внутренние функции являются приватными.


Внутренние механизмы

Внутри библиотеки присутствуют:

toDate(input) — конвертация входного значения в объект Date:

// Аналог внутренней реализации
function toDate(input) {
  if (input instanceof Date) return input;
  if (typeof input === 'number') return new Date(input);
  return new Date(input);
}

formatDiff(diff, locale) — вычисление строки по числовой разнице. Не экспортируется.

run(node, locale) — создание таймера для одного элемента.


Создание служебного модуля поверх timeago.js

Можно создать набор утилит, дополняющих стандартные методы:

// src/timeago-utils.js

import { format } from 'timeago.js';

/**
 * Форматирует дату относительно текущего момента с fallback.
 */
export function safeFormat(date, locale = 'ru', fallback = '') {
  if (!date) return fallback;

  const d = new Date(date);
  if (isNaN(d.getTime())) return fallback;

  return format(d, locale);
}

/**
 * Возвращает метаданные вместе со строкой.
 */
export function formatWithMeta(date, locale = 'ru') {
  const d    = new Date(date);
  const diff = Date.now() - d.getTime();
  const str  = format(d, locale);

  return {
    label:    str,
    isPast:   diff > 0,
    ageMs:    Math.abs(diff),
    ageHours: Math.abs(diff) / 3600000,
    ageDays:  Math.abs(diff) / 86400000,
  };
}

/**
 * Определяет "свежесть" даты.
 */
export function freshness(date) {
  const ageMs = Date.now() - new Date(date).getTime();
  if (ageMs < 60000)      return 'just';     // < 1 мин
  if (ageMs < 3600000)    return 'fresh';    // < 1 ч
  if (ageMs < 86400000)   return 'recent';   // < 1 д
  if (ageMs < 604800000)  return 'old';      // < 1 нед
  return 'ancient';
}

Утилита watchVisibility

Обновлять таймеры только для видимых элементов:

import { render, cancel } from 'timeago.js';

function watchVisibility(nodes, locale = 'ru') {
  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        render(entry.target, locale);
      } else {
        cancel(entry.target);
      }
    });
  });

  nodes.forEach(node => observer.observe(node));

  return {
    destroy() {
      nodes.forEach(node => {
        observer.unobserve(node);
        cancel(node);
      });
      observer.disconnect();
    }
  };
}

Утилита batchRender

Пакетная инициализация с задержкой между элементами:

import { render } from 'timeago.js';

function batchRender(nodes, locale = 'ru', batchSize = 50) {
  const arr = Array.from(nodes);
  let i = 0;

  function renderBatch() {
    const batch = arr.slice(i, i + batchSize);
    render(batch, locale);
    i += batchSize;

    if (i < arr.length) {
      requestAnimationFrame(renderBatch);
    }
  }

  requestAnimationFrame(renderBatch);
}

Утилита createTimer

Ручное управление интервалами без render:

import { format } from 'timeago.js';

function createTimer(element, date, locale = 'ru') {
  let timeoutId = null;

  function getDelay() {
    const diff = Math.abs(Date.now() - new Date(date).getTime());
    if (diff < 60000)     return 10000;   // каждые 10с
    if (diff < 3600000)   return 60000;   // каждую минуту
    if (diff < 86400000)  return 3600000; // каждый час
    return 86400000;
  }

  function tick() {
    element.textContent = format(date, locale);
    timeoutId = setTimeout(tick, getDelay());
  }

  tick();

  return { stop: () => clearTimeout(timeoutId) };
}

Утилита formatAll

Форматирование всех элементов без автообновления:

import { format } from 'timeago.js';

function formatAll(selector = '[datetime]', locale = 'ru') {
  document.querySelectorAll(selector).forEach(el => {
    const date = el.getAttribute('datetime');
    if (date) el.textContent = format(date, locale);
  });
}

Утилита wrapFormat

Декоратор для добавления дополнительной логики вокруг format:

import { format } from 'timeago.js';

function wrapFormat(beforeFn, afterFn) {
  return function(date, locale = 'ru', opts) {
    if (beforeFn) beforeFn(date, locale);
    const result = format(date, locale, opts);
    if (afterFn) return afterFn(result, date, locale);
    return result;
  };
}

const trackedFormat = wrapFormat(
  (date) => analytics.track('timeago_format', { date }),
  (result) => result
);