likes
comments
collection
share

简单实现时间格式化函数的封装+正则表达式几个知识点的简单介绍+函数实现的思路分享

作者站长头像
站长
· 阅读数 25

一、起源

 在很多的项目或者练习中,都会遇到要将时间转换为自己需要的格式, 比如是2022-11-14 10:48:22又或者是2022-11-14又或者是10:48:22。其实想要实现转换是非常简单的,只需要使用时间对象对应的方法即可。  最近刚好有遇到类似的需求,封装了两种简单的时间格式转换的函数,分享给大家。

文章知识点

  1. 时间格式化封装的两个函数
  2. 正则表达式分组、分组反向引用、范围选择的知识点
  3. String.prototype.replace方法与正则表达式联用的知识点

二、时间格式化函数源码

1. 基础版时间格式化

  这个版本的时间格式化函数是通过传入时间戳或传入时间对象以及所需的格式类型来取得对应的时间格式字符串,代码的逻辑比较简单,就不过多介绍。

function getDate(timestamp, type) {   
   // 对输入的事件源进行判断,若无法正常的转换为时间则抛出错误
   try{
    // 将时间对象转换为时间戳
    timestamp = typeof timestamp === 'object'
      ? timestamp.getTime()
      : timestamp;
  } catch {
    throw new Error('请输入正确的时间戳或时间对象');
  }    
  
  var len = timestamp.toString().length;

  if (len < 10) {
    timestamp *= 10 ** (13 - len);
  }

  var dt = new Date(timestamp),
    y = dt.getFullYear(),
    M = completeZero(dt.getMonth() + 1),
    d = completeZero(dt.getDate()),
    h = completeZero(dt.getHours()),
    m = completeZero(dt.getMinutes()),
    s = completeZero(dt.getSeconds());

  switch (type) {
    case 'dt':
      return y + '-' + M + '-' + d + ' ' + h + ':' + m + ':' + s;
    case 'd':
      return y + '-' + M + '-' + d;
    case 't':
      return h + ':' + m + ':' + s;
    default:
      return y + '-' + M + '-' + d + ' ' + h + ':' + m + ':' + s;
  }

  function completeZero(time) {
    return time < 10 ? '0' + time : time;
  }
}

2. 利用正则表达式来实现时间格式转换 🦉

 这个方法就相对第一种方法而言有难度一点点,但难度也就是在正则表达式上,如果大家有用过正则表达式对HTML进行模板替换,那这一种方法也是几乎没有难度的。

function getDate(timestamp, format) {
 // 对输入的事件源进行判断,若无法正常的转换为时间则抛出错误
    try{
      // 将时间对象转换为时间戳
      timestamp = typeof timestamp === 'object'
        ? timestamp.getTime()
        : timestamp;
    } catch {
      throwErr();
    }        
    
    var len = timestamp.toString().length,
      regex = new RegExp(/(([A-z])\2{1,3})/gim);

    // 若传入的时间戳是小于13位
    if (len < 13) {
      timestamp *= 10 ** (13 - len);
    }

    var dt = new Date(timestamp);

    if (dt.toString() === 'Invalid Date') {          
      throwErr();
    }
    
    var yyyy = dt.getFullYear(),
      MM = completeZero(dt.getMonth() + 1),
      dd = completeZero(dt.getDate()),
      HH = completeZero(dt.getHours()),
      mm = completeZero(dt.getMinutes()),
      ss = completeZero(dt.getSeconds()),
      valid = regex.test(format);        
    
    if (valid) {
      return format.replace(regex, (_, key) => {
        return {
          yyyy,
          MM,
          dd,
          HH,
          mm,
          ss
        }[key];
      });   
    } else {          
      return dt;
    }

    function throwErr() {
      throw new Error('请输入正确的时间戳或时间对象');
    }      

    function completeZero(time) {
      return time < 10 
        ? '0' + time 
        : time;
    }
  }

三、方法二的实现思路

 这两个方法可能是不够完整的,还有很多种异常输入没有做处理,但我觉得也没什么必要,毕竟是为了编写代码方便而写的工具类函数。

1. 简单谈一下正则的含义

重点就是这么一个式子:/(([A-z]\2{1,3}))/gim,它的含义是匹配2-4个重复的大小写字母,如yyyyMMdd,其中用到了正则中的分组、分组反向引用以及多个相同值的简写。

分组

在正则表达式中,你可以使用()来设定一个分组,在匹配成功后也会根据分组返回对应匹配到的内容,同时也可以进行一个关键的操作,也就是分组反向引用

举一个简单的例子:

  <script type='text/javascript'>
    const str = 'yyyy-MM-dd HH:mm:ss',
      regex = /([A-z])([A-z])/gim;    
    console.log(regex.exec(str));
  </script>

简单实现时间格式化函数的封装+正则表达式几个知识点的简单介绍+函数实现的思路分享

分组反向引用

当我们选中分组的时候就会从左往右自动有一个分组需要由1-n,利用\n(分组号)就等于写了两遍第一个分组的内容。

举个例子:

// 意思为捕获字符串中连续的两个a的内容
/aa/
// 而使用分组捕获可以这么写,与上述的写法效果一致
/(a)\1/

匹配长度之{}

在使用正则表达式的时候我们很经常遇到匹配相同值多次,如/\s\s\s\s\s\s\s/匹配7个连续的空格,在一定数量内还是可控的,但当这个匹配数量非常大的时候,通过一个个来写就不太合适了,因此可以使用匹配长度{from, to}。匹配from-to之间的连续个数,同时如果{}中只填一个数字的时候匹配连续n个对应值。

经典之举个例子:

// 这个正则表达式匹配的是5-10个连续字母组成的字母字符串
/[A-z]{5, 10}/
// 如果只填写一个数, 意味着匹配3个连续字母组成的字母字符串
/[A-z]{3}/
// 第二个值也可以不写,匹配的就是大于前者的连续值,这个应该比较好理解
/[A-z]/{3,}

2. 聊回函数中的正则表达式

函数中用到的正则表达式通过上面简单分享的正则基础内容想必大家会更好理解一点。/(([A-z]\2{1,3}))/gim我使用了两个分组是因为在后续的分组捕获中我是需要得到完整的匹配结果,当然也可以使用node而不是用key,在下一节中再分享给大家。那么这个代码就很好理解,我将[A-z]作为匹配2组,再利用分组反向引用来匹配连续的4组相同字母

3. String.prototype.replace方式与正则表达式的联动

String原型对象上的replace方法不止可以根据字符串来替换内容,同样也可以根据正则表达式来匹配、替换内容,同时可以使用函数的形式进行更高级的替换,这里就直接以本文中的正则替换为例吧。

// 这里的format就是调用方法时传入的时间格式
format.replace(regex, (node, key) => {
  // 当前这个函数就类似于执行了exec,其中的node是匹配到的内容, key其实是指的匹配组的第一组
  // 本质上参数应该写为 $, $1, $2 ... $n
  // 第一个参数表示匹配的内容,之后的参数便都是各个匹配组的内容
  // return 是将匹配到的内容修改为return的值,这里使用定义一个对象且根据当前key来获取对象属性的方式返回
  return {
    yyyy,
    MM,
    dd,
    HH,
    mm,
    ss
  }[key];
});

四、总结

 以上便是本篇文章的全部内容,回顾一下,本片文章简单的介绍了正则表达式的几个小知识点,以及分享了笔者写的两种时间格式化的工具函数、以及对其中稍微有难度的方法的解释,当然上文的代码还存在非常多的不足,也会有很多没有考虑到的地方,如果笔者存在知识点的理解错误,也希望读者可以在评论区告知,万分感谢您的观看。我是Donp1,我们下次再见!