const ISO_DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?$/ export function isIsoDateTimeString(value: unknown): value is string { return typeof value === 'string' && ISO_DATE_TIME_PATTERN.test(value.trim()) } export function formatDateTime(value: string | null | undefined, fallback = '-') { const normalized = String(value || '').trim() if (!normalized) { return fallback } const date = new Date(normalized) if (Number.isNaN(date.getTime())) { return normalized.replace('T', ' ').replace('Z', '') } const year = date.getFullYear() const month = String(date.getMonth() + 1).padStart(2, '0') const day = String(date.getDate()).padStart(2, '0') const hours = String(date.getHours()).padStart(2, '0') const minutes = String(date.getMinutes()).padStart(2, '0') const seconds = String(date.getSeconds()).padStart(2, '0') return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` } export function normalizeDateTimeValue(value: unknown): unknown { if (Array.isArray(value)) { return value.map((item) => normalizeDateTimeValue(item)) } if (value && typeof value === 'object') { return Object.fromEntries( Object.entries(value).map(([key, currentValue]) => [ key, normalizeDateTimeValue(currentValue), ]), ) } if (isIsoDateTimeString(value)) { return formatDateTime(value, '') } return value } export function stringifyDisplayJson(value: unknown, space = 2) { return JSON.stringify(normalizeDateTimeValue(value), null, space) }