amanpay / web /src /utils /format.ts
MHamdan's picture
CI deploy 895c0ed
adb91eb verified
Raw
History Blame Contribute Delete
1.72 kB
// Date/time presented in Asia/Riyadh by default (backend-configured tz).
export function formatDateTime(epochSeconds: number, locale = 'en', tz = 'Asia/Riyadh'): string {
try {
return new Intl.DateTimeFormat(locale === 'ar' ? 'ar-SA' : 'en-GB', {
dateStyle: 'medium', timeStyle: 'short', timeZone: tz,
}).format(new Date(epochSeconds * 1000))
} catch {
return new Date(epochSeconds * 1000).toISOString()
}
}
// Any real transaction is after this floor; anything before it (epoch 0, a placeholder
// like `2`, or `1970-01-01T00:00:00Z`) is treated as "no real timestamp".
const MIN_VALID_MS = Date.UTC(2000, 0, 1)
/**
* Safe timestamp formatter. Accepts an epoch-seconds number OR an ISO string. Returns `null`
* for missing/empty/invalid/epoch-equivalent values so the caller can show a localized
* "Date unavailable" fallback — it NEVER fabricates the current date and never renders 1970.
*/
export function formatDateTimeSafe(
value: number | string | null | undefined,
locale = 'en',
tz = 'Asia/Riyadh',
): string | null {
if (value === null || value === undefined) return null
let ms: number
if (typeof value === 'number') {
if (!Number.isFinite(value)) return null
ms = value * 1000 // backend convention: epoch seconds
} else {
const s = value.trim()
if (s === '') return null
ms = new Date(s).getTime() // ISO string (already ms-based)
}
if (!Number.isFinite(ms) || ms < MIN_VALID_MS) return null
try {
return new Intl.DateTimeFormat(locale === 'ar' ? 'ar-SA' : 'en-GB', {
dateStyle: 'medium', timeStyle: 'short', timeZone: tz,
}).format(new Date(ms))
} catch {
return null
}
}