const CHINA_TIME_ZONE = "Asia/Shanghai"; const PLAIN_DATE_TIME_RE = /^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?$/; function pad(value: string | undefined) { return value || "00"; } function formatPlainChinaDateTime(value: string, withSeconds = false) { const match = value.trim().match(PLAIN_DATE_TIME_RE); if (!match) { return null; } const [, year, month, day, hour, minute, second] = match; if (!hour || !minute) { return `${year}/${month}/${day}`; } return withSeconds ? `${year}/${month}/${day} ${hour}:${minute}:${pad(second)}` : `${year}/${month}/${day} ${hour}:${minute}`; } export function formatChinaDateTime(value?: string | number | null, options?: { seconds?: boolean }) { if (value === null || value === undefined || value === "") { return "—"; } const raw = String(value).trim(); const plain = formatPlainChinaDateTime(raw, Boolean(options?.seconds)); if (plain) { return plain; } const date = new Date(raw); if (Number.isNaN(date.getTime())) { return raw; } return new Intl.DateTimeFormat("zh-CN", { timeZone: CHINA_TIME_ZONE, year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: options?.seconds ? "2-digit" : undefined, hour12: false, }).format(date); } export function formatChinaShortDateTime(value?: string | number | null) { if (value === null || value === undefined || value === "") { return ""; } const raw = String(value).trim(); const plain = formatPlainChinaDateTime(raw); if (plain) { return plain.slice(5); } const date = new Date(raw); if (Number.isNaN(date.getTime())) { return raw; } return new Intl.DateTimeFormat("zh-CN", { timeZone: CHINA_TIME_ZONE, month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", hour12: false, }).format(date); } export function formatChinaTime(value?: string | number | null) { if (value === null || value === undefined || value === "") { return ""; } const raw = String(value).trim(); const match = raw.match(PLAIN_DATE_TIME_RE); if (match?.[4] && match?.[5]) { return `${match[4]}:${match[5]}:${pad(match[6])}`; } const date = new Date(raw); if (Number.isNaN(date.getTime())) { return raw; } return new Intl.DateTimeFormat("zh-CN", { timeZone: CHINA_TIME_ZONE, hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false, }).format(date); }