94 lines
2.8 KiB
TypeScript
94 lines
2.8 KiB
TypeScript
/**
|
|
* Shared ru-RU formatters — single source for dates/numbers across the app.
|
|
* All timestamps are ISO strings from the API.
|
|
*/
|
|
|
|
const packetFmt = new Intl.NumberFormat('ru-RU', {
|
|
notation: 'compact',
|
|
maximumFractionDigits: 1,
|
|
})
|
|
|
|
const numberFmt = new Intl.NumberFormat('ru-RU')
|
|
|
|
const shortDateTimeFmt = new Intl.DateTimeFormat('ru-RU', {
|
|
day: '2-digit',
|
|
month: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
})
|
|
|
|
const dateTimeFmt = new Intl.DateTimeFormat('ru-RU')
|
|
|
|
const stampDateTimeFmt = new Intl.DateTimeFormat('ru-RU', {
|
|
day: '2-digit',
|
|
month: '2-digit',
|
|
year: 'numeric',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit',
|
|
})
|
|
|
|
const timeFmt = new Intl.DateTimeFormat('ru-RU', {
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit',
|
|
})
|
|
|
|
const relativeFmt = new Intl.RelativeTimeFormat('ru-RU', { numeric: 'auto' })
|
|
|
|
/** Compact packet counter: 1,2K / 3,4M */
|
|
export function formatPackets(n: number | undefined | null): string {
|
|
if (n === undefined || n === null) return '—'
|
|
return packetFmt.format(n)
|
|
}
|
|
|
|
export function formatNumber(n: number | undefined | null): string {
|
|
if (n === undefined || n === null) return '—'
|
|
return numberFmt.format(n)
|
|
}
|
|
|
|
/** dd.MM HH:mm — dense "seen" stamps in grids/cards */
|
|
export function formatShortDateTime(iso: string | null | undefined): string {
|
|
if (!iso) return '—'
|
|
const t = Date.parse(iso)
|
|
if (Number.isNaN(t)) return '—'
|
|
return shortDateTimeFmt.format(new Date(t))
|
|
}
|
|
|
|
/** Full locale date-time for detail panels */
|
|
export function formatDateTime(iso: string | null | undefined): string {
|
|
if (!iso) return '—'
|
|
const t = Date.parse(iso)
|
|
if (Number.isNaN(t)) return iso
|
|
return dateTimeFmt.format(new Date(t))
|
|
}
|
|
|
|
/** dd.MM.yyyy HH:mm:ss — block-stats "seen" stamps */
|
|
export function formatStampDateTime(iso: string | null | undefined): string {
|
|
if (!iso) return '—'
|
|
const t = Date.parse(iso)
|
|
if (Number.isNaN(t)) return iso
|
|
return stampDateTimeFmt.format(new Date(t))
|
|
}
|
|
|
|
export function formatTime(d: Date): string {
|
|
return timeFmt.format(d)
|
|
}
|
|
|
|
/** «2 минуты назад» / «5 часов назад»; старше 7 дней — полная дата. */
|
|
export function formatRelativeTime(iso: string | null | undefined): string {
|
|
if (!iso) return '—'
|
|
const t = Date.parse(iso)
|
|
if (Number.isNaN(t)) return '—'
|
|
const diffMs = t - Date.now()
|
|
const absMin = Math.round(Math.abs(diffMs) / 60_000)
|
|
if (absMin < 1) return 'только что'
|
|
const sign = diffMs < 0 ? -1 : 1
|
|
if (absMin < 60) return relativeFmt.format(sign * absMin, 'minute')
|
|
const absHours = Math.round(absMin / 60)
|
|
if (absHours < 24) return relativeFmt.format(sign * absHours, 'hour')
|
|
const absDays = Math.round(absHours / 24)
|
|
if (absDays < 7) return relativeFmt.format(sign * absDays, 'day')
|
|
return formatDateTime(iso)
|
|
}
|