(timestamp: number)
| 1 | export function formatRelativeTime(timestamp: number) { |
| 2 | const now = Date.now(); |
| 3 | const diffSeconds = Math.round((timestamp - now) / 1000); |
| 4 | const absSeconds = Math.abs(diffSeconds); |
| 5 | if (absSeconds < 5) { |
| 6 | return "now"; |
| 7 | } |
| 8 | if (absSeconds < 60) { |
| 9 | const value = Math.max(1, Math.round(absSeconds)); |
| 10 | return diffSeconds < 0 ? `${value}s ago` : `in ${value}s`; |
| 11 | } |
| 12 | if (absSeconds < 60 * 60) { |
| 13 | const value = Math.max(1, Math.round(absSeconds / 60)); |
| 14 | return diffSeconds < 0 ? `${value}m ago` : `in ${value}m`; |
| 15 | } |
| 16 | const ranges: { unit: Intl.RelativeTimeFormatUnit; seconds: number }[] = [ |
| 17 | { unit: "year", seconds: 60 * 60 * 24 * 365 }, |
| 18 | { unit: "month", seconds: 60 * 60 * 24 * 30 }, |
| 19 | { unit: "week", seconds: 60 * 60 * 24 * 7 }, |
| 20 | { unit: "day", seconds: 60 * 60 * 24 }, |
| 21 | { unit: "hour", seconds: 60 * 60 }, |
| 22 | { unit: "minute", seconds: 60 }, |
| 23 | { unit: "second", seconds: 1 }, |
| 24 | ]; |
| 25 | const range = |
| 26 | ranges.find((entry) => absSeconds >= entry.seconds) || |
| 27 | ranges[ranges.length - 1]; |
| 28 | if (!range) { |
| 29 | return "now"; |
| 30 | } |
| 31 | const value = Math.round(diffSeconds / range.seconds); |
| 32 | const formatter = new Intl.RelativeTimeFormat(undefined, { numeric: "auto" }); |
| 33 | return formatter.format(value, range.unit); |
| 34 | } |
| 35 | |
| 36 | export function formatRelativeTimeShort(timestamp: number) { |
| 37 | const now = Date.now(); |
no outgoing calls
no test coverage detected