timeago.js не имеет встроенного механизма управления часовыми поясами. Библиотека вычисляет разницу между двумя timestamp-значениями, оба из которых привязаны к UTC. Поэтому часовой пояс не влияет на результат при правильном использовании входных данных.
Вычисление разницы внутри библиотеки:
const diff = Date.now() - new Date(input).getTime();
Оба значения — Date.now() и .getTime() —
возвращают UTC-миллисекунды. Это означает:
import { format } from 'timeago.js';
// Строка явно в UTC — результат одинаков в любом часовом поясе
format('2025-05-26T10:00:00Z', 'ru');
// UTC+3 — тоже корректно
format('2025-05-26T13:00:00+03:00', 'ru');
Оба примера выше математически эквивалентны, так как оба указывают на один и тот же момент UTC.
// Без суффикса — браузер интерпретирует как локальное время
format('2025-05-26T10:00:00'); // поведение зависит от браузера
В Chrome и Firefox такая строка трактуется как локальное время. В старых Safari — поведение могло быть иным.
Если сервер отдаёт строки без пояса и подразумевает UTC:
const rawDate = '2025-05-26T10:00:00';
format(rawDate + 'Z', 'ru'); // явно добавить Z
format('2025-05-26');
ECMAScript трактует строку YYYY-MM-DD как UTC-полночь.
Это означает: если пользователь в UTC+3, то “26 мая” будет показано как
“3 часа назад” в 00:00 UTC, хотя пользователь ждёт “сегодня в
полночь”.
Явное добавление локального времени решает проблему:
// Если дата предназначена для локального времени:
const localMidnight = new Date(2025, 4, 26); // месяц 0-based
format(localMidnight, 'ru');
Если сервер возвращает локальное время сервера (например, UTC+5) без явного указания пояса:
const serverLocalTime = '2025-05-26T10:00:00'; // UTC+5 без указания
// Некорректно: браузер считает это локальным временем клиента
format(serverLocalTime, 'ru'); // ошибка, если у клиента не UTC+5
Правильное решение — всегда передавать UTC с суффиксом Z
или со смещением:
const serverUTC = '2025-05-26T05:00:00Z'; // UTC+5 → UTC = -5 часов
format(serverUTC, 'ru'); // корректно
Если приходят строки без пояса и их нужно считать UTC:
function parseAsUTC(str) {
if (str.endsWith('Z') || str.includes('+') || str.includes('-', 10)) {
return new Date(str);
}
return new Date(str + 'Z');
}
format(parseAsUTC('2025-05-26T10:00:00'), 'ru');
Если приходят строки без пояса и их нужно считать локальным временем:
function parseAsLocal(str) {
// Парсим компоненты и создаём Date как локальное время
const [date, time = '00:00:00'] = str.split('T');
const [year, month, day] = date.split('-').map(Number);
const [hour, minute, second] = time.split(':').map(Number);
return new Date(year, month - 1, day, hour, minute, second);
}
format(parseAsLocal('2025-05-26T10:00:00'), 'ru');
На сервере Node.js часовой пояс определяется переменной окружения
TZ:
TZ=Europe/Moscow node server.js
Это влияет на new Date() без явного пояса. Для
предсказуемого поведения:
Z.timeago.js не показывает временны́е зоны в строке вывода. Если нужен вывод типа “2 часа назад (UTC+3)”, это реализуется постобработкой:
import { format } from 'timeago.js';
function formatWithZone(date, locale = 'ru') {
const relative = format(date, locale);
const zone = Intl.DateTimeFormat().resolvedOptions().timeZone;
return `${relative} (${zone})`;
}
timeago.js не предоставляет инструментов для конвертации зон. Для этого используются специализированные библиотеки:
import { zonedTimeToUtc } from 'date-fns-tz';
import { format } from 'timeago.js';
// Создать дату в конкретной зоне и конвертировать в UTC
const localDate = zonedTimeToUtc('2025-05-26T10:00:00', 'America/New_York');
format(localDate, 'en_US');
Z).relativeDate явно, чтобы избежать
расхождений между сервером и клиентом.