Работа с будущими датами

timeago.js поддерживает форматирование не только прошедших, но и будущих дат. Если переданная дата позже текущего момента, библиотека автоматически использует вторую форму строки из локали (futureString).


Базовый принцип

Внутри библиотека определяет направление:

const diff = new Date(input).getTime() - Date.now();

if (diff > 0) {
  // Будущее — использует futureString из [past, future]
} else {
  // Прошлое — использует pastString
}

Простые примеры

import { format } from 'timeago.js';

// Через 5 минут
format(Date.now() + 1000 * 60 * 5,          'ru'); // → "через 5 минут"

// Через 2 часа
format(Date.now() + 1000 * 60 * 60 * 2,     'ru'); // → "через 2 часа"

// Через 1 день
format(Date.now() + 1000 * 60 * 60 * 24,    'ru'); // → "через 1 день"

// Через 3 недели
format(Date.now() + 1000 * 60 * 60 * 24 * 21, 'ru'); // → "через 3 недели"

// Через 6 месяцев
format(Date.now() + 1000 * 60 * 60 * 24 * 180, 'ru'); // → "через 6 месяцев"

Дедлайны и обратный отсчёт

import { format } from 'timeago.js';

const deadline = new Date('2025-06-15T23:59:59Z');

format(deadline, 'ru'); // → "через 20 дней"

Это удобно для:

  • задач и тикетов с дедлайнами;
  • событий в календаре;
  • счётчиков до начала акции;
  • времени до доставки заказа.

Автообновление для будущих дат

<time id="event-time" datetime="2025-06-15T23:59:59Z"></time>
import { render } from 'timeago.js';

const node = document.getElementById('event-time');
render(node, 'ru');

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

через 20 дней
→ через 19 дней
→ через 18 часов
→ через 5 минут
→ только что
→ 1 минуту назад

После наступления момента вывод плавно переключается на прошедшее время.


Отображение “просрочено” при прошедшем дедлайне

import { format } from 'timeago.js';

function formatDeadline(date, locale = 'ru') {
  const diff = new Date(date).getTime() - Date.now();

  if (diff < 0) {
    const overdue = Math.abs(diff);
    const days    = Math.floor(overdue / (1000 * 60 * 60 * 24));

    if (days === 0) return 'просрочено сегодня';
    return `просрочено на ${days} ${days === 1 ? 'день' : 'дней'}`;
  }

  return format(date, locale);
}

Цветовая индикация срочности

import { format } from 'timeago.js';

function urgencyClass(date) {
  const diff = new Date(date).getTime() - Date.now();

  if (diff < 0)             return 'overdue';
  if (diff < 3600000)       return 'critical';   // < 1 часа
  if (diff < 86400000)      return 'warning';    // < 1 дня
  if (diff < 7 * 86400000)  return 'soon';       // < 1 недели
  return 'normal';
}

Будущие даты в компоненте дедлайна

import { useEffect, useState } from 'react';
import { format } from 'timeago.js';

function Deadline({ date }: { date: string }) {
  const [label, setLabel] = useState(() => format(date, 'ru'));

  useEffect(() => {
    const id = setInterval(() => {
      setLabel(format(date, 'ru'));
    }, 60000);

    return () => clearInterval(id);
  }, [date]);

  const isPast = new Date(date).getTime() < Date.now();

  return (
    <span className={isPast ? 'overdue' : 'upcoming'}>
      {label}
    </span>
  );
}

Планирование публикаций

import { format } from 'timeago.js';

const scheduledPosts = [
  { title: 'Анонс', publishAt: '2025-05-27T09:00:00Z' },
  { title: 'Статья', publishAt: '2025-05-28T14:00:00Z' },
  { title: 'Вебинар', publishAt: '2025-06-05T18:00:00Z' },
];

scheduledPosts.forEach(post => {
  const relative = format(post.publishAt, 'ru');
  console.log(`"${post.title}" — ${relative}`);
});

Вывод:

"Анонс" — через 1 день
"Статья" — через 2 дня
"Вебинар" — через 10 дней

Будущие даты в локали (проверка futureString)

Убедиться, что локаль корректно обрабатывает будущее:

import { register, format } from 'timeago.js';

register('test_locale', (number, index) => {
  const pairs = [
    ['только что', 'прямо сейчас'],
    ['%s сек. назад', 'через %s сек.'],
    // ...
  ];
  return pairs[index];
});

// Проверка будущего
format(Date.now() + 30000, 'test_locale');  // → "через 30 сек."
format(Date.now() + 90000, 'test_locale');  // → "прямо сейчас" (index 0) или "через X сек."

Предупреждение о некорректном будущем

Если дата “в будущем” передана по ошибке (неверный формат или часовой пояс), функция всё равно вернёт строку с “через…”. Для отладки можно добавить проверку:

function debugFormat(date, locale = 'ru') {
  const diff = new Date(date).getTime() - Date.now();

  if (diff > 0) {
    console.debug('[timeago] Future date detected:', date, `(+${Math.round(diff / 1000)}s)`);
  }

  return format(date, locale);
}

Форматирование будущих дат в расписании

const schedule = [
  { event: 'Встреча',  time: new Date(Date.now() + 1000 * 60 * 30) },  // через 30 мин
  { event: 'Созвон',   time: new Date(Date.now() + 1000 * 60 * 90) },  // через 1.5 ч
  { event: 'Презент.', time: new Date(Date.now() + 1000 * 60 * 60 * 5) }, // через 5 ч
];

schedule.forEach(({ event, time }) => {
  console.log(`${event}: ${format(time, 'ru')}`);
});