资讯专栏INFORMATION COLUMN

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

roadtogeek / 481人阅读

摘要:下面实现日期格式的解析,要把传入的日期格式做匹配,然后从对象解析出对应的值,再拼到一块。

最近在翻看原来写的工具函数中,发现了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(), // 年 : 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
    h: date.getHours(), // 时
    hh: paddNum(date.getHours()), // 时
    mm: paddNum(date.getMinutes()), // 分
    ss: paddNum(date.getSeconds()) // 秒
  }
  return format.replace(/([a-z])(1)*/ig, m => cfg[m])
}

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94933.html

相关文章

  • 【从0到1】分步实现一个出生日期正则达式(JavaScript)

    摘要:简言在表单验证中,经常会用正则表达式做出生日期校验。声明本文目的是为了阐述如何编写一个正则表达式的过程。综上所述,正则表达式是强大的,但并不是万能的,因此不要过份地依赖和滥用正则。 简言 在表单验证中,经常会用正则表达式做出生日期校验。本文把出生日期分割成几个部分,分步地介绍了实现一个出生日期校验的完整过程。相信您在理解了本篇的内容后,对如何编写和如何应用正则表达式会有进一步的理解和体...

    shaonbean 评论0 收藏0
  • MongoDB指南---3、MongoDB基础知识-数据类型

    摘要:如将构造函数作为函数进行调用即不包括的方式,返回的是日期的字符串表示,而非日期对象。如果不注意这一点,没有始终使用日期构造函数,将得到一堆混乱的日期对象和日期的字符串。关于日期类的完整解释,以及构造函数的参数格式,参见规范节。 上一篇文章:MongoDB指南---2、MongoDB基础知识-文档、集合、数据库、客户端下一篇文章:MongoDB指南---4、MongoDB基础知识-使用M...

    aervon 评论0 收藏0
  • MongoDB指南---3、MongoDB基础知识-数据类型

    摘要:如将构造函数作为函数进行调用即不包括的方式,返回的是日期的字符串表示,而非日期对象。如果不注意这一点,没有始终使用日期构造函数,将得到一堆混乱的日期对象和日期的字符串。关于日期类的完整解释,以及构造函数的参数格式,参见规范节。 上一篇文章:MongoDB指南---2、MongoDB基础知识-文档、集合、数据库、客户端下一篇文章:MongoDB指南---4、MongoDB基础知识-使用M...

    tunny 评论0 收藏0
  • JavaScript正则达式学习笔记(二) - 打怪升级

    摘要:本文接上篇,基础部分相对薄弱的同学请移步正则表达式学习笔记一理论基础。正则表达式标志符全局匹配,即找到所有匹配的。方法返回结果的格式不一致问题这个问题上文正则表达式学习笔记一理论基础也有体现,这里再单独拿来说一说,以加深记忆。 showImg(https://segmentfault.com/img/remote/1460000014261596?w=600&h=338); 本文接上篇...

    Jioby 评论0 收藏0
  • JavaScript 编程精解 中文第三版 九、正则达式

    摘要:使用构造器时,需要将模式书写成普通的字符串,因此反斜杠的使用规则与往常相同。构造器的后四个参数小时分钟秒毫秒是可选的,如果用户没有指定这些参数,则参数的值默认为。 来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:Regular Expressions 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 部分参考了《JavaScript...

    Pluser 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<