const dateTimeFormatter = new Intl.DateTimeFormat('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, }); const relativeTimeFormatter = new Intl.RelativeTimeFormat('zh-CN', { numeric: 'auto', }); function toDate(value: string | Date | null | undefined) { if (!value) { return null; } const normalizedValue = typeof value === 'string' ? value.replace(' ', 'T') : value; const date = normalizedValue instanceof Date ? normalizedValue : new Date(normalizedValue); return Number.isNaN(date.getTime()) ? null : date; } export function formatDateTime(value: string | Date | null | undefined) { const date = toDate(value); if (!date) { return '—'; } return dateTimeFormatter.format(date).replace(/\//g, '-'); } export function formatRelativeTime(value: string | Date | null | undefined) { const date = toDate(value); if (!date) { return '—'; } const diffMs = date.getTime() - Date.now(); const diffSeconds = Math.round(diffMs / 1000); const absSeconds = Math.abs(diffSeconds); if (absSeconds < 60) { return relativeTimeFormatter.format(diffSeconds, 'second'); } const diffMinutes = Math.round(diffSeconds / 60); if (Math.abs(diffMinutes) < 60) { return relativeTimeFormatter.format(diffMinutes, 'minute'); } const diffHours = Math.round(diffMinutes / 60); if (Math.abs(diffHours) < 24) { return relativeTimeFormatter.format(diffHours, 'hour'); } const diffDays = Math.round(diffHours / 24); if (Math.abs(diffDays) < 30) { return relativeTimeFormatter.format(diffDays, 'day'); } const diffMonths = Math.round(diffDays / 30); if (Math.abs(diffMonths) < 12) { return relativeTimeFormatter.format(diffMonths, 'month'); } const diffYears = Math.round(diffMonths / 12); return relativeTimeFormatter.format(diffYears, 'year'); }