import { computed, type ComputedRef } from 'vue' import { injectI18n } from '../providers/i18n' export type Formatter = (value: Date | number | null | undefined, options?: FormatOptions) => string export interface FormatOptions { roundingMode?: 'halfExpand' | 'floor' | 'ceil' } const formatters = new Map>() export function useRelativeTime(): Formatter { const { locale } = injectI18n() const formatterRef = computed( () => new Intl.RelativeTimeFormat(locale.value, { numeric: 'auto', style: 'long', }), ) if (!formatters.has(locale.value)) { formatters.set(locale.value, formatterRef) } return (value: Date | number | null | undefined) => { if (value == null) { return '' } const date = value instanceof Date ? value : new Date(value) if (Number.isNaN(date.getTime())) { return '' } const now = Date.now() const diff = date.getTime() - now const seconds = Math.round(diff / 1000) const minutes = Math.round(diff / 60000) const hours = Math.round(diff / 3600000) const days = Math.round(diff / 86400000) const weeks = Math.round(diff / 604800000) const months = Math.round(diff / 2629746000) const years = Math.round(diff / 31556952000) const rtf = formatterRef.value if (Math.abs(seconds) < 60) { return rtf.format(seconds, 'second') } else if (Math.abs(minutes) < 60) { return rtf.format(minutes, 'minute') } else if (Math.abs(hours) < 24) { return rtf.format(hours, 'hour') } else if (Math.abs(days) < 7) { return rtf.format(days, 'day') } else if (Math.abs(weeks) < 4) { return rtf.format(weeks, 'week') } else if (Math.abs(months) < 12) { return rtf.format(months, 'month') } else { return rtf.format(years, 'year') } } }