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] || '';
  });
}

感谢阅读,敬请斧正!

相关推荐
遗憾随她而去.10 分钟前
前端首屏加载时间的度量:FCP、LCP等指标的规范理解
前端
TAEHENGV12 分钟前
React Native for OpenHarmony 实战:数学练习实现
javascript·react native·react.js
CDwenhuohuo12 分钟前
安卓app巨坑 nvue后者页面要写画笔绘制功能nvue canvas
前端·javascript·vue.js
一只小bit17 分钟前
Qt 事件:覆盖介绍、处理、各种类型及运用全详解
前端·c++·qt·cpp
Never_Satisfied22 分钟前
在JavaScript / HTML中,HTML元素自定义属性使用指南
开发语言·javascript·html
前端 贾公子28 分钟前
husky 9.0升级指南
javascript
人道领域32 分钟前
JavaWeb从入门到进阶(前端工程化)
前端
shughui42 分钟前
APP、Web、H5、iOS与Android的区别及关系
android·前端·ios
Amumu121381 小时前
React Router 6介绍
前端·react.js·前端框架
南村群童欺我老无力.1 小时前
Flutter 框架跨平台鸿蒙开发 - 打造表情包制作器应用
开发语言·javascript·flutter·华为·harmonyos