/** `datetime-local` 控件用:本地时间的 `YYYY-MM-DDTHH:mm:ss` */ export function occurredOnToLocalInputValue(d: Date | string | number): string { const date = d instanceof Date ? d : new Date(d) if (Number.isNaN(date.getTime())) { return '' } const pad = (n: number) => String(n).padStart(2, '0') return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}` } /** 解析 `datetime-local`(按用户本地时区构造瞬间,再交给 `toISOString()` 发给服务端) */ export function parseLocalDatetimeInput(s: string): Date { const m = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?/.exec(s.trim()) if (!m) { throw new Error('invalid datetime-local') } const y = Number(m[1]) const mo = Number(m[2]) const day = Number(m[3]) const h = Number(m[4]) const mi = Number(m[5]) const sec = m[6] !== undefined ? Number(m[6]) : 0 return new Date(y, mo - 1, day, h, mi, sec, 0) } /** 列表 / 公开页展示:年月日 星期 时:分:秒(24 小时) */ export function formatOccurredOnDisplay(d: Date | string | number, locale = 'zh-CN'): string { const date = d instanceof Date ? d : new Date(d) if (Number.isNaN(date.getTime())) { return '—' } return new Intl.DateTimeFormat(locale, { year: 'numeric', month: 'long', day: 'numeric', weekday: 'short', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false, }).format(date) } export function occurredOnToIsoAttr(d: Date | string | number): string { const date = d instanceof Date ? d : new Date(d) if (Number.isNaN(date.getTime())) { return '' } return date.toISOString() } /** 文章列表:发布日期(年月日 + 星期) */ export function formatPublishedDateOnly( d: Date | string | number | null | undefined, locale = 'zh-CN', ): string { if (d == null) { return '' } const date = d instanceof Date ? d : new Date(d) if (Number.isNaN(date.getTime())) { return '—' } return new Intl.DateTimeFormat(locale, { year: 'numeric', month: 'long', day: 'numeric', weekday: 'short', }).format(date) }