TypeScript 封装 Date 格式化函数:简洁又高效

引言

在项目开发中,日期时间格式化展示是常见的功能需求,但由于不同场景对格式的要求各异,团队中每个开发者都独立编写代码来满足各自需求,这导致项目中出现大量重复且冗余的代码。这种现象不仅降低了开发效率,也违背了代码规范中关于 避免重复代码(DRY-Don't Repeat Yourself)保持一致性 的原则。

避免过度封装 :虽然 DRY 原则 强调避免重复代码,但过度封装可能会导致代码复杂难懂。在封装时需要权衡代码的通用性和灵活性。

基于以上思考,封装一个通用的日期格式化函数,不仅能减少重复代码,还能显著提升代码的可复用性和可维护性。通过学习和整合项目组中同学们的优秀实现,我记录下自己的学习过程,并尝试封装出一个易于使用的日期格式化工具函数。

代码实现

  1. MDN的Date文档
  2. 通过指定占位符定义 format 格式,使用 replace 方法将占位符替换为具体的日期时间值

定义 占位符 规则

输入 示例 描述
YY 25 两位数的年份
YYYY 2025 四位数的年份
M 1-12 月份/从 1 开始
MM 01-12 月份/两位数
MMM Jan-Dec 简写英文的月份名称
MMMM January-December 完整英文的月份名称
MMMMM 一月-十二月 大写汉字的月份名称
D 1-31 月份里的一天
DD 01-31 月份里的一天/两位数
W 0 0-6,分别表示星期日-星期六
WW 周日 周x
WWW 星期日 星期x
Q 1 1-4
QQ 一季度 一季度--四季度
H 0-23 小时/24 小时制
HH 00-23 小时/24 小时制/两位数
h 1-12 小时/12 小时制
hh 01-12 小时/12 小时制/两位数
A AM / PM 上午/下午 大写
a am / pm 上午/下午 小写
m 0-59 分钟
mm 00-59 分钟/两位数
s 0-59
ss 00-59 秒/两位数
S 0-9 毫秒/一位数
SS 00-99 毫秒/两位数
SSS 000-999 毫秒/三位数

源码

ts 复制代码
function dateFormatter(format: string = 'YYYY-MM-DD HH:mm:ss', date: Date | string | number  = new Date()): string {
  let parsedDate: Date;
  if (date instanceof Date) {
    parsedDate = date;
  } else if (typeof date === 'string' || typeof date === 'number') {
    parsedDate = new Date(date);
    if (isNaN(parsedDate.getTime())) {
      parsedDate = new Date();
    }
  } else {
    parsedDate = new Date()
  }
  // 获取日期的基本信息
  const year = parsedDate.getFullYear();
  const month = parsedDate.getMonth(); // 0 表示 1 月
  const day = parsedDate.getDate();
  const weekday = parsedDate.getDay(); // 0 表示星期日
  const hour = parsedDate.getHours();
  const minute = parsedDate.getMinutes();
  const second = parsedDate.getSeconds();
  const millisecond = parsedDate.getMilliseconds();


  // 星期和月份的常量定义
  const FULL_WEEKDAYS = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
  const SHORT_WEEKDAYS = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
  const MONTHS_CHINESE = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
  const MONTHS_SHORT_EN = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
  const MONTHS_LONG_EN = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
  const QUARTERS = ['一季度', '二季度', '三季度', '四季度'];

  // 获取季度的函数
  const getQuarter = (month: number) => Math.ceil((month + 1) / 3);

  // 映射表:格式化占位符到实际值的映射
  const PLACEHOLDER_MAPPING = {
    // 年份
    YYYY: year.toString(),
    YY: year.toString().slice(-2),

    // 月份
    M: (month + 1).toString(),
    MM: (month + 1).toString().padStart(2, '0'),
    MMM: MONTHS_SHORT_EN[month],
    MMMM: MONTHS_LONG_EN[month],
    MMMMM: MONTHS_CHINESE[month],

    // 日期
    D: day.toString(),
    DD: day.toString().padStart(2, '0'),

    // 星期
    W: weekday.toString(),
    WW: SHORT_WEEKDAYS[weekday],
    WWW: FULL_WEEKDAYS[weekday],

    // 季度
    Q: getQuarter(month).toString(),
    QQ: QUARTERS[getQuarter(month) - 1],

    // 时间(24小时制)
    H: hour.toString(),
    HH: hour.toString().padStart(2, '0'),

    // 时间(12小时制)
    h: (hour % 12 || 12).toString(),
    hh: (hour % 12 || 12).toString().padStart(2, '0'),
    A: hour >= 12 ? 'PM' : 'AM',
    a: hour >= 12 ? 'pm' : 'am',

    // 分钟和秒
    m: minute.toString(),
    mm: minute.toString().padStart(2, '0'),
    s: second.toString(),
    ss: second.toString().padStart(2, '0'),

    // 毫秒
    S: millisecond.toString(),
    SS: millisecond.toString().padStart(2, '0'),
    SSS: millisecond.toString().padStart(3, '0')
  };

  // 替换逻辑:根据格式字符串中的占位符替换为实际值
  return format.replace(/Y+|M+|D+|W+|Q+|H+|h+|A|a|m+|s+|S+/g, (match) => {
    return PLACEHOLDER_MAPPING[match] || '';
  });
}

感谢阅读,敬请斧正!

相关推荐
(ღ星辰ღ)1 分钟前
js应用opencv
开发语言·javascript·opencv
浩~~6 分钟前
HTML5 中实现盒子水平垂直居中的方法
java·服务器·前端
互联网搬砖老肖11 分钟前
Web 架构之故障自愈方案
前端·架构·github
天上掉下来个程小白16 分钟前
添加购物车-02.代码开发
java·服务器·前端·后端·spring·微信小程序·苍穹外卖
网络空间小黑1 小时前
WEB渗透测试----信息收集
服务器·前端·网络·安全·web安全·网络安全
水银嘻嘻1 小时前
web 自动化之 Unittest 应用:报告&装饰器&断言
前端·python·自动化
巴巴_羊2 小时前
AJAX原理
前端·javascript·ajax
良木林2 小时前
HTML难点小记:一些简单标签的使用逻辑和实用化
前端·html
一个游离的指针3 小时前
ES6基础特性
前端·javascript·es6
layman05283 小时前
ES6/ES11知识点
前端·ecmascript·es6