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) } /** 抢单大厅发布耗时格式化(仅内部打手可见):发布 <1m / 发布 5m / 发布 1h 20m / 发布 1d 4h */ export function formatPublishedElapsedTime( value: string | null | undefined, nowMs = Date.now(), ): string { const normalized = String(value || '').trim() if (!normalized) return '' const date = new Date(normalized) const time = date.getTime() if (Number.isNaN(time)) return '' const diffSeconds = Math.max(0, Math.floor((nowMs - time) / 1000)) if (diffSeconds < 60) { return '发布 <1m' } const diffMinutes = Math.floor(diffSeconds / 60) if (diffMinutes < 60) { return `发布 ${diffMinutes}m` } const diffHours = Math.floor(diffMinutes / 60) const remMinutes = diffMinutes % 60 if (diffHours < 24) { return remMinutes > 0 ? `发布 ${diffHours}h ${remMinutes}m` : `发布 ${diffHours}h` } const diffDays = Math.floor(diffHours / 24) const remHours = diffHours % 24 return remHours > 0 ? `发布 ${diffDays}d ${remHours}h` : `发布 ${diffDays}d` }