隐藏
«

封装时间格式组件

时间:2025-12-2 17:37     作者:suxiaojun     分类:


// utils/formatDate.ts

/**
 * 按指定格式格式化时间戳
 * @param timestamp 时间戳(number | string),可为毫秒数或可被 new Date() 解析的字符串
 * @param format 输出格式,默认 YYYY-MM-DD hh:mm:ss
 *  - YYYY: 4 位年份
 *  - YY: 2 位年份
 *  - MM/M: 月(两位/一位)
 *  - DD/D: 日(两位/一位)
 *  - HH/H: 24 小时制(两位/一位)
 *  - hh/h: 12 小时制(两位/一位)
 *  - mm/m: 分钟(两位/一位)
 *  - ss/s: 秒(两位/一位)
 *  - A: AM / PM
 */
export function formatDate(timestamp: number | string, format = 'YYYY-MM-DD hh:mm:ss'): string {
  // 若传入空值,返回空字符串
  if (!timestamp) return ''

  let ts: any = null

  // 如果 timestamp 不是数字,则直接作为日期字符串处理
  // 否则转为数字(时间戳)
  if (isNaN(Number(timestamp))) {
    ts = timestamp
  } else {
    ts = Number(timestamp)
  }

  const date = new Date(ts)

  // new Date 无法解析时,返回 Invalid Date
  if (isNaN(date.getTime())) return 'Invalid Date'

  // 基本日期结构
  const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()
  const hours24 = date.getHours()
  const minutes = date.getMinutes()
  const seconds = date.getSeconds()

  // 处理 12 小时制 AM/PM
  const ampm = hours24 >= 12 ? 'PM' : 'AM'
  const hours12 = hours24 % 12 || 12 // 0 点转换成 12 点

  // 格式中是否出现 A(表示使用 12 小时制)
  const use12Hour = format.includes('A')

  /**
   * 占位符映射表
   * 不同的 key 会对应不同的日期组件内容
   */
  const map: Record<string, string> = {
    YYYY: String(year),
    YY: String(year).slice(-2),
    MM: String(month).padStart(2, '0'),
    M: String(month),
    DD: String(day).padStart(2, '0'),
    D: String(day),
    hh: String(hours12).padStart(2, '0'),
    h: String(hours12),
    HH: String(hours24).padStart(2, '0'),
    H: String(hours24),
    mm: String(minutes).padStart(2, '0'),
    m: String(minutes),
    ss: String(seconds).padStart(2, '0'),
    s: String(seconds),
    A: ampm, // AM/PM
  }

  // 如果格式包含 A,则 hh/h 应使用 12 小时制
  if (use12Hour) {
    map.hh = String(hours12).padStart(2, '0')
    map.h = String(hours12)
  } else {
    // 未使用 A,则 hh/h 默认等同于 24 小时制(HH/H)
    map.hh = map.HH
    map.h = map.H
  }

  // 遍历所有占位符并进行替换
  let formatted = format
  for (const key in map) {
    formatted = formatted.replace(new RegExp(key, 'g'), map[key])
  }

  return formatted
}