fix: 格式化时间
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m48s

This commit is contained in:
sexygoat
2026-05-21 14:53:36 +08:00
parent dfb78006ac
commit a69f972766

View File

@@ -167,41 +167,101 @@ export function formatDateRange(startDate: string, endDate: string): string {
/**
* 格式化日期时间
* @param date 日期字符串或时间戳支持Unix时间戳秒自动检测
* 规则:
* 1. 带明确日期文本的字符串按原始时间文本展示,不跟随客户端本地时区转换
* 2. 纯数字时间戳支持秒/毫秒自动识别
* 3. Date/时间戳这类“只有绝对时刻、没有原始展示时区”的值,按 UTC 稳定输出
* @param date 日期字符串或时间戳(支持 Unix 时间戳秒/毫秒,自动检测)
* @param format 格式化模板,默认 'YYYY-MM-DD HH:mm:ss'
* @returns 格式化后的日期字符串
*/
type DateTimeParts = {
year: string
month: string
day: string
hours: string
minutes: string
seconds: string
}
const DATE_TIME_TEXT_REGEX =
/^(\d{4})-(\d{2})-(\d{2})(?:[T\s](\d{2})(?::(\d{2})(?::(\d{2})(?:\.\d+)?)?)?)?(?:Z|[+-]\d{2}:?\d{2})?$/
function formatDateTimeParts(parts: DateTimeParts, format: string): string {
return format
.replace('YYYY', parts.year)
.replace('MM', parts.month)
.replace('DD', parts.day)
.replace('HH', parts.hours)
.replace('mm', parts.minutes)
.replace('ss', parts.seconds)
}
function parseDateTimeText(dateText: string): DateTimeParts | null {
const match = dateText.trim().match(DATE_TIME_TEXT_REGEX)
if (!match) return null
return {
year: match[1],
month: match[2],
day: match[3],
hours: match[4] ?? '00',
minutes: match[5] ?? '00',
seconds: match[6] ?? '00'
}
}
function normalizeTimestamp(timestamp: number): number {
const absoluteValue = Math.abs(timestamp)
// 10 位左右按秒处理13 位左右按毫秒处理
if (absoluteValue >= 1e9 && absoluteValue < 1e12) {
return timestamp * 1000
}
return timestamp
}
function getUtcDateTimeParts(date: Date): DateTimeParts {
return {
year: String(date.getUTCFullYear()),
month: String(date.getUTCMonth() + 1).padStart(2, '0'),
day: String(date.getUTCDate()).padStart(2, '0'),
hours: String(date.getUTCHours()).padStart(2, '0'),
minutes: String(date.getUTCMinutes()).padStart(2, '0'),
seconds: String(date.getUTCSeconds()).padStart(2, '0')
}
}
export function formatDateTime(
date: string | number | Date | undefined | null,
format: string = 'YYYY-MM-DD HH:mm:ss'
): string {
if (!date) return '-'
if (date === undefined || date === null || date === '') return '-'
let d: Date
const numDate = typeof date === 'string' ? Number(date) : date
if (typeof numDate === 'number' && numDate > 1000000000 && numDate < 2000000000) {
d = new Date(numDate * 1000)
} else {
d = new Date(date)
if (typeof date === 'string') {
const trimmedDate = date.trim()
if (!trimmedDate) return '-'
const parsedText = parseDateTimeText(trimmedDate)
if (parsedText) {
return formatDateTimeParts(parsedText, format)
}
if (isNaN(d.getTime())) return '-'
const numericTimestamp = Number(trimmedDate)
if (!Number.isNaN(numericTimestamp)) {
const parsedDate = new Date(normalizeTimestamp(numericTimestamp))
if (Number.isNaN(parsedDate.getTime())) return '-'
return formatDateTimeParts(getUtcDateTimeParts(parsedDate), format)
}
}
// 使用 UTC 方法获取时间
const year = d.getUTCFullYear()
const month = String(d.getUTCMonth() + 1).padStart(2, '0')
const day = String(d.getUTCDate()).padStart(2, '0')
const hours = String(d.getUTCHours()).padStart(2, '0')
const minutes = String(d.getUTCMinutes()).padStart(2, '0')
const seconds = String(d.getUTCSeconds()).padStart(2, '0')
const parsedDate = new Date(
typeof date === 'number' ? normalizeTimestamp(date) : date
)
if (Number.isNaN(parsedDate.getTime())) return '-'
return format
.replace('YYYY', String(year))
.replace('MM', month)
.replace('DD', day)
.replace('HH', hours)
.replace('mm', minutes)
.replace('ss', seconds)
return formatDateTimeParts(getUtcDateTimeParts(parsedDate), format)
}