/** * Утилиты форматирования времени для Рублокс 3D. * * Сервер сохраняет время в формате 'YYYY-MM-DD HH:MM:SS' БЕЗ маркера TZ. * Это UTC (контейнер запущен в UTC), но строка ISO-парсера JS воспринимает * её как local time → разница с реальным локальным. * * Эти функции трактуют сырое время как UTC и приводят к локальному. */ /** * Парсит 'YYYY-MM-DD HH:MM:SS' (как UTC) или ISO ('...Z' / '+03:00') в Date. */ export function parseServerTime(s) { if (!s) return null; if (typeof s !== 'string') return null; // Если уже ISO с TZ — Date справится if (/Z$|[+-]\d{2}:?\d{2}$/.test(s)) { const d = new Date(s); return isNaN(d.getTime()) ? null : d; } // 'YYYY-MM-DD HH:MM:SS' — добавляем 'Z' чтобы интерпретировать как UTC const iso = s.replace(' ', 'T') + 'Z'; const d = new Date(iso); return isNaN(d.getTime()) ? null : d; } /** HH:MM в локальном поясе пользователя. */ export function formatTimeShort(s) { const d = parseServerTime(s); if (!d) return ''; return d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' }); } /** Полное «01.05.2026 11:33» в локальном поясе. */ export function formatDateTime(s) { const d = parseServerTime(s); if (!d) return ''; return d.toLocaleString(undefined, { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit', }); } /** «5 минут назад» / «вчера» / «01.05.2026 11:33». */ export function formatRelative(s) { const d = parseServerTime(s); if (!d) return ''; const diffSec = (Date.now() - d.getTime()) / 1000; if (diffSec < 0) return formatTimeShort(s); // в будущем — fallback if (diffSec < 60) return 'только что'; if (diffSec < 3600) return `${Math.floor(diffSec / 60)} мин назад`; if (diffSec < 86400) { const h = Math.floor(diffSec / 3600); return `${h} ${pluralRu(h, ['час', 'часа', 'часов'])} назад`; } if (diffSec < 86400 * 2) return 'вчера в ' + formatTimeShort(s); if (diffSec < 86400 * 7) { const days = Math.floor(diffSec / 86400); return `${days} ${pluralRu(days, ['день', 'дня', 'дней'])} назад`; } return formatDateTime(s); } function pluralRu(n, forms) { const mod10 = n % 10; const mod100 = n % 100; if (mod10 === 1 && mod100 !== 11) return forms[0]; if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) return forms[1]; return forms[2]; }