正则表达式在日期处理的一个应用

前端之家收集整理的这篇文章主要介绍了正则表达式在日期处理的一个应用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

最近在翻看原来写的工具函数中,发现了formatDate这个工具函数,原来只是在使用,具体的实现原理没有仔细研究过,这次就来分析一下它的实现,了解一下正则表达式的一个实战应用。

函数功能

formatDate 函数接受两个参数,日期对象和格式参数,可以根据不同的格式参数将事件对象转换成日期格式,大致使用如下

formatDate(new Date(),'yy-mm-dd')    // 18-05-13
formatDate(new Date(),'yyyy-MM-dd hh:mm') // "2018-05-13 16:35"

当然也可以把函数挂载在prototype上面,这样就只需要一个参数了,这个后续再说。

实现思路

实现思路比较简单,就是利用,Date提供的函数,比如getMonthgetFullYear函数先把Date对象拆解出必要的部分。年月日小时分钟秒等,然后再根据传入的参数进行组合,得到想要的效果。这里有几个处理过程中需要注意的地方。

  • 对于1位的数字应该可以支持选择补0也可以不补0
formatDate(new Date(),'yyyy-M-dd') // "2018-5-13"
formatDate(new Date(),'yyyy-MM-dd') // "2018-05-13"
  • 对于月份因为是从0开始计数的,所以要+1月,不是加1s啊
  • 支持参数的各种组合

实现过程

因为需要支持各种组合,所以需要一个对象将个部分存储下来,根据参数的格式能够快速的解析出来对应的值。对象的格式大致如下

var cfg = {
    yyyy: date.getFullYear(),// 年 : 4位
    yy: date.getFullYear().toString().substring(2),// 年 : 2位
    M: date.getMonth() + 1,// 月 : 如果1位的时候不补0
    MM: paddNum(date.getMonth() + 1),// 月 : 如果1位的时候补0
    d: date.getDate(),// 日 : 如果1位的时候不补0
    dd: paddNum(date.getDate()),// 日 : 如果1位的时候补0
    hh: paddNum(date.getHours()),// 时
    mm: paddNum(date.getMinutes()),// 分
    ss: paddNum(date.getSeconds()) // 秒
  }

双位补0单位不补0,补0的过程封装成一个函数paddNum,自然想到的是用正则表达式来判断是否是1位,很容易写出如下代码

let paddNum = num => {
  if (/^\d$/.test(num)) {
     return '0' + num
  }
  return num
}

不过还可以使用字符串提供的正则表达式replace功能简化这个过程,使用捕获组来获取匹配的值,再+0,如果没有匹配,就返回本身,这也正是我们想要的,这里提前需要把数字转换成字符串。

let paddNum = num => num.toString().replace(/^(\d)$/,'0$1')

这样每个日期的数据处理部分就做完了。
下面实现日期格式的解析,要把传入的日期格式做匹配,然后从对象解析出对应的值,再拼到一块。
分析传入日期的格式,都是yyyydd这种重叠的格式,这就需要针对每一个匹配出来的值,都要匹配到与其相同的一组值,也就是如果匹配到y,那就要把紧跟在y后面所有的y都匹配出来,比如yyyyyy等,直到遇到首个不是y的字符停止。这就需要在匹配环节记住匹配的部分并重复匹配,捕获组又派上了用场。 /([a-z])(\1)*/\1可以代替匹配到的字符,进而组成新的匹配条件,这样的匹配条件就是那种想要的重叠格式了。
所以解析的过程如下

format.replace(/([a-z])(\1)*/ig,m => cfg[m])

整合

稍作整理,这个工具函数就组合起来了

const formatDate = (date=new Date(),format='yyyy-MM-dd hh:mm:ss') => {
  // 单位补0
  let paddNum = num => num.toString().replace(/^(\d)$/,'0$1')
  // 指定格式字符
  var cfg = {
    yyyy: date.getFullYear(),// 日 : 如果1位的时候补0
    h: date.getHours(),// 时
    hh: paddNum(date.getHours()),// 分
    ss: paddNum(date.getSeconds()) // 秒
  }
  return format.replace(/([a-z])(\1)*/ig,m => cfg[m])
}

可以看出用好正则表达式的捕获组,可以大大简化代码量,逻辑看上去也很清楚。

原文链接:https://www.f2er.com/regex/357501.html

猜你在找的正则表达式相关文章