Пользовательские форматы позволяют полностью изменить вид строки,
которую возвращает библиотека. Это может быть сокращённый формат,
описательный без чисел, смешанный — сначала относительное, потом
абсолютное. Всё это реализуется через кастомные локали и обёртки над
format.
import { register, format } from 'timeago.js';
register('ru_abbr', (number, index) => {
return [
['сейчас', 'сейчас'],
['%sс', 'ч/%sс'],
['%sс', 'ч/%sс'],
['1м', 'ч/1м'],
['%sм', 'ч/%sм'],
['1ч', 'ч/1ч'],
['%sч', 'ч/%sч'],
['1д', 'ч/1д'],
['%sд', 'ч/%sд'],
['1нед', 'ч/1нед'],
['%sнед', 'ч/%sнед'],
['1мес', 'ч/1мес'],
['%sмес', 'ч/%sмес'],
['1г', 'ч/1г'],
['%sл', 'ч/%sл'],
][index];
});
format(Date.now() - 1000 * 60 * 45, 'ru_abbr');
// → "45м"
register('ru_mixed', (number, index) => {
if (index === 0) return ['только что', 'скоро'];
if (index <= 2) return ['несколько секунд назад', 'через несколько секунд'];
if (index === 3) return ['минуту назад', 'через минуту'];
if (index === 4 && number < 10) return [`${number} минут назад`, `через ${number} минут`];
return [`${number} мин. назад`, `через ${number} мин.`];
});
import { format } from 'timeago.js';
function richFormat(date, locale = 'ru') {
const diff = Date.now() - new Date(date).getTime();
const WEEK = 1000 * 60 * 60 * 24 * 7;
if (diff > WEEK) {
return new Intl.DateTimeFormat('ru', {
day: 'numeric',
month: 'long',
year: 'numeric',
hour: '2-digit',
minute:'2-digit',
}).format(new Date(date));
}
return format(date, locale);
}
Вывод:
5 минут назад
4 часа назад
1 день назад
26 мая 2025 г., 10:00 ← для старых дат
function withTooltip(date, locale = 'ru') {
const relative = format(date, locale);
const absolute = new Intl.DateTimeFormat('ru', {
dateStyle: 'medium',
timeStyle: 'short',
}).format(new Date(date));
return { relative, absolute };
}
В HTML:
<time class="ago" title="{{ absolute }}">{{ relative }}</time>
import { format } from 'timeago.js';
function formatWithTime(date, locale = 'ru') {
const diff = Date.now() - new Date(date).getTime();
const DAY = 1000 * 60 * 60 * 24;
if (diff < DAY) {
return format(date, locale);
}
const time = new Intl.DateTimeFormat('ru', {
hour: '2-digit',
minute: '2-digit',
}).format(new Date(date));
return `${format(date, locale)} в ${time}`;
}
formatWithTime(new Date(Date.now() - 1000 * 60 * 60 * 26), 'ru');
// → "1 день назад в 08:30"
register('ru_notify', (number, index) => {
return [
['•', '•'],
['только что', 'скоро'],
['только что', 'скоро'],
['1 мин', 'скоро'],
['%s мин', 'через %s мин'],
['1 ч', 'через 1 ч'],
['%s ч', 'через %s ч'],
['вчера', 'завтра'],
['%s дн', 'через %s дн'],
['нед', 'через нед'],
['%s нед', 'через %s нед'],
['мес', 'через мес'],
['%s мес', 'через %s мес'],
['год', 'через год'],
['%s л', 'через %s л'],
][index];
});
В интерфейсах чата часто используется сокращённый стиль:
register('ru_chat', (number, index) => {
return [
['сейч.', 'сейч.'],
['%дс', '%дс'],
['%дс', '%дс'],
['1м', 'ч1м'],
['%м', 'ч%м'],
['1ч', 'ч1ч'],
['%ч', 'ч%ч'],
['вчера', 'завтра'],
['%дн', 'ч%дн'],
['нед', 'чнед'],
['%нед', 'ч%нед'],
['мес', 'чмес'],
['%мес', 'ч%мес'],
['год', 'чгод'],
['%л', 'ч%л'],
][index];
});
register('ru_approx', (number, index) => {
const prefix = (index >= 3) ? '~' : '';
const strs = [
['только что', 'скоро'],
['%s сек. назад', 'через %s сек.'],
// ...
][index];
return strs ? [prefix + strs[0], prefix + strs[1]] : strs;
});
Если не хочется менять локаль, форматирование можно модифицировать снаружи:
import { format } from 'timeago.js';
function formatDecorated(date, locale = 'ru') {
const str = format(date, locale);
const isPast = new Date(date).getTime() < Date.now();
if (isPast) {
return `? ${str}`; // только если допустимы эмодзи
}
return `⏳ ${str}`;
}
function templateFormat(date, template = '{time} назад', locale = 'ru') {
const raw = format(date, locale);
return template.replace('{time}', raw);
}
templateFormat(Date.now() - 3600000, 'Опубликовано {time}');
// → "Опубликовано 1 час назад"