Относительное время — способ представления даты и времени не в
абсолютном формате (2026-05-27 14:00), а относительно
текущего момента:
5 минут назадчерез 2 днявчера1 hour agoin 3 weeksБиблиотека Globalize предоставляет механизм локализации подобных выражений на основе данных CLDR (Common Locale Data Repository). Форматирование автоматически учитывает:
Для работы с относительным временем необходимы:
const Globalize = require("globalize");
require("cldr-data").entireSupplemental();
require("cldr-data").entireMainFor("en", "ru");
Globalize.load(
require("cldr-data/supplemental/likelySubtags.json"),
require("cldr-data/supplemental/timeData.json"),
require("cldr-data/supplemental/weekData.json"),
require("cldr-data/main/en/dateFields.json"),
require("cldr-data/main/ru/dateFields.json")
);
После загрузки данных создаётся экземпляр локали:
const ru = new Globalize("ru");
const en = new Globalize("en");
formatRelativeTimeОсновной инструмент библиотеки — метод:
globalize.formatRelativeTime(value, unit)
| Параметр | Описание |
|---|---|
value |
числовое значение |
unit |
единица времени |
| Единица | Значение |
|---|---|
second |
секунды |
minute |
минуты |
hour |
часы |
day |
дни |
week |
недели |
month |
месяцы |
year |
годы |
ru.formatRelativeTime(-5, "second");
Результат:
5 секунд назад
Положительное значение:
ru.formatRelativeTime(10, "second");
Результат:
через 10 секунд
ru.formatRelativeTime(-3, "minute");
Результат:
3 минуты назад
en.formatRelativeTime(-3, "minute");
Результат:
3 minutes ago
ru.formatRelativeTime(2, "hour");
Результат:
через 2 часа
ru.formatRelativeTime(-1, "day");
Результат:
1 день назад
Знак числа определяет направление времени.
| Значение | Интерпретация |
|---|---|
| отрицательное | прошлое |
| положительное | будущее |
0 |
текущий момент |
Пример:
ru.formatRelativeTime(-7, "day");
7 дней назад
ru.formatRelativeTime(7, "day");
через 7 дней
Одно из главных преимуществ Globalize — корректное склонение числительных.
Русский язык имеет сложные правила множественного числа:
ru.formatRelativeTime(-1, "minute");
ru.formatRelativeTime(-2, "minute");
ru.formatRelativeTime(-5, "minute");
Результаты:
1 минуту назад
2 минуты назад
5 минут назад
Для английского языка:
en.formatRelativeTime(-1, "minute");
en.formatRelativeTime(-2, "minute");
Результаты:
1 minute ago
2 minutes ago
Все правила берутся из CLDR автоматически.
CLDR содержит разные стили отображения времени:
Пример сокращённых вариантов:
через 3 ч.
5 мин назад
2 нед.
В некоторых версиях Globalize стиль можно указать через опции форматтера.
Для повышения производительности рекомендуется создавать форматтер заранее.
ru.formatRelativeTime(-5, "day");
const formatter = ru.relativeTimeFormatter("day");
formatter(-5);
formatter(10);
Результаты:
5 дней назад
через 10 дней
При каждом вызове библиотека:
Предварительно созданный форматтер избавляет от повторной подготовки.
Особенно важно это:
const messages = [
{ text: "Сообщение 1", minutes: -1 },
{ text: "Сообщение 2", minutes: -5 },
{ text: "Сообщение 3", minutes: -20 }
];
const formatter = ru.relativeTimeFormatter("minute");
messages.forEach(message => {
console.log(
message.text,
formatter(message.minutes)
);
});
Результат:
Сообщение 1 1 минуту назад
Сообщение 2 5 минут назад
Сообщение 3 20 минут назад
Часто требуется преобразовывать разницу дат автоматически:
function formatTimeAgo(date, globalize) {
const diff = Date.now() - date.getTime();
const seconds = Math.floor(diff / 1000);
if (seconds < 60) {
return globalize.formatRelativeTime(
-seconds,
"second"
);
}
const minutes = Math.floor(seconds / 60);
if (minutes < 60) {
return globalize.formatRelativeTime(
-minutes,
"minute"
);
}
const hours = Math.floor(minutes / 60);
if (hours < 24) {
return globalize.formatRelativeTime(
-hours,
"hour"
);
}
const days = Math.floor(hours / 24);
return globalize.formatRelativeTime(
-days,
"day"
);
}
Использование:
const postDate = new Date(Date.now() - 3600 * 1000);
console.log(
formatTimeAgo(postDate, ru)
);
Результат:
1 час назад
Относительное время подходит не только для прошлого.
const daysLeft = 12;
ru.formatRelativeTime(daysLeft, "day");
Результат:
через 12 дней
const hoursLeft = 3;
ru.formatRelativeTime(hoursLeft, "hour");
Результат:
через 3 часа
DateОбычно вычисляется разница между двумя датами.
const now = new Date();
const createdAt = new Date(
now.getTime() - 2 * 60 * 60 * 1000
);
const diffHours = Math.floor(
(createdAt - now) / (1000 * 60 * 60)
);
ru.formatRelativeTime(diffHours, "hour");
Результат:
2 часа назад
Относительное время применяется:
| Сценарий | Пример |
|---|---|
| мессенджеры | 2 минуты назад |
| комментарии | час назад |
| соцсети | вчера |
| уведомления | через 5 минут |
| таймеры | через 2 дня |
Во многих интерфейсах надписи должны обновляться автоматически.
const formatter =
ru.relativeTimeFormatter("minute");
function render() {
const createdAt =
Date.now() - 5 * 60 * 1000;
const diffMinutes = Math.floor(
(createdAt - Date.now()) / 60000
);
console.log(
formatter(diffMinutes)
);
}
setInterval(render, 60000);
Разные языки имеют разные правила.
через 1 день
через 2 дня
через 5 дней
za 1 dzień
za 2 dni
za 5 dni
Используются отдельные формы для:
CLDR хранит все эти правила.
Intl.RelativeTimeFormatСовременный Javascript содержит встроенный API:
Intl.RelativeTimeFormat
Пример:
const rtf = new Intl.RelativeTimeFormat("ru");
rtf.format(-5, "minute");
Результат:
5 минут назад
Несмотря на наличие встроенного API, Globalize остаётся востребованным благодаря:
Globalize позволяет объединять:
const dateFormatter =
ru.dateFormatter({
datetime: "medium"
});
const relativeFormatter =
ru.relativeTimeFormatter("minute");
const createdAt =
new Date(Date.now() - 300000);
console.log(
"Создано:",
dateFormatter(createdAt)
);
console.log(
relativeFormatter(-5)
);
Результат:
Создано: 27 мая 2026 г., 14:10:00
5 минут назад
Ошибка:
E_MISSING_CLDR
Причина:
Globalize.load(...)
не был вызван.
dateFields.jsonОтносительное время хранится именно там.
Необходимо:
require("cldr-data/main/ru/dateFields.json")
Ошибка:
ru.formatRelativeTime(-5, "minutes");
Правильно:
ru.formatRelativeTime(-5, "minute");
Используются только значения в единственном числе.
Полный CLDR может занимать значительный объём.
Для уменьшения размера подключают только необходимые данные.
Globalize.load(
require("cldr-data/main/ru/dateFields.json")
);
Globalize.load(
require("cldr-data/main/en/dateFields.json"),
require("cldr-data/main/ru/dateFields.json"),
require("cldr-data/main/de/dateFields.json")
);
const locales = {
ru: new Globalize("ru"),
en: new Globalize("en"),
de: new Globalize("de")
};
locales.ru.formatRelativeTime(-1, "day");
locales.en.formatRelativeTime(-1, "day");
locales.de.formatRelativeTime(-1, "day");
Результаты:
1 день назад
1 day ago
vor 1 Tag
const comments = [
{
user: "Alex",
createdAt:
Date.now() - 1000 * 60 * 3
},
{
user: "Kate",
createdAt:
Date.now() - 1000 * 60 * 50
}
];
const formatter =
ru.relativeTimeFormatter("minute");
comments.forEach(comment => {
const diffMinutes = Math.floor(
(comment.createdAt - Date.now()) /
60000
);
console.log(
comment.user,
formatter(diffMinutes)
);
});
Результат:
Alex 3 минуты назад
Kate 50 минут назад
function formatCountdown(targetDate) {
const diff =
targetDate.getTime() - Date.now();
const days = Math.floor(
diff / (1000 * 60 * 60 * 24)
);
return ru.formatRelativeTime(
days,
"day"
);
}
const eventDate =
new Date(Date.now() + 5 * 86400000);
console.log(
formatCountdown(eventDate)
);
Результат:
через 5 дней
При большом количестве вызовов желательно:
Globalize повторно;Механизм работы состоит из нескольких этапов:
CLDR хранит шаблоны в dateFields.json.
Пример структуры:
{
"day": {
"relativeTime-type-future": {
"relativeTimePattern-count-one":
"через {0} день",
"relativeTimePattern-count-few":
"через {0} дня",
"relativeTimePattern-count-many":
"через {0} дней"
}
}
}
Именно эти данные используются движком форматирования.
Globalize поддерживает:
Intl;function TimeAgo({ createdAt, globalize }) {
const diffMinutes = Math.floor(
(createdAt - Date.now()) / 60000
);
return (
<span>
{
globalize.formatRelativeTime(
diffMinutes,
"minute"
)
}
</span>
);
}
export default {
props: ["createdAt"],
computed: {
relativeTime() {
const diffMinutes = Math.floor(
(this.createdAt - Date.now()) /
60000
);
return this.$globalize
.formatRelativeTime(
diffMinutes,
"minute"
);
}
}
};
На сервере относительное время часто формируется заранее.
app.get("/", (req, res) => {
const globalize = new Globalize("ru");
const createdAt =
Date.now() - 1000 * 60 * 15;
const relative =
globalize.formatRelativeTime(
-15,
"minute"
);
res.render("index", {
relative
});
});