分析一段正则: 关于时间格式化 format/sdf/dateformat/date

一段关于日期格式化的正则 /\byyyy|yy|MM|M|dd|d|HH|H|mm|m|ss|s\b/g
更新于: 2023-08-09 10:27:50

源码

来源 weui-miniprogram 项目里的一段源码

function format(time, reg) {
  const date = typeof time === 'string' ? new Date(time) : time
  const map = {}
  map.yyyy = date.getFullYear()
  map.yy = ('' + map.yyyy).substr(2)
  map.M = date.getMonth() + 1
  map.MM = (map.M < 10 ? '0' : '') + map.M
  map.d = date.getDate()
  map.dd = (map.d < 10 ? '0' : '') + map.d
  map.H = date.getHours()
  map.HH = (map.H < 10 ? '0' : '') + map.H
  map.m = date.getMinutes()
  map.mm = (map.m < 10 ? '0' : '') + map.m
  map.s = date.getSeconds()
  map.ss = (map.s < 10 ? '0' : '') + map.s

  return reg.replace(/\byyyy|yy|MM|M|dd|d|HH|H|mm|m|ss|s\b/g, $1 => map[$1])
}

正则

/\byyyy|yy|MM|M|dd|d|HH|H|mm|m|ss|s\b/g

问题分析

/\b:这是一个单词边界,确保我们只匹配独立的日期和时间部分。这样可以避免在词组内部匹配到不必要的内容。

  • 简化源码
  • \b: 边界词
  • /g: 多次匹配,直到没有结果为止
  • yyyy|yy|MM|M|dd|d|HH|H|mm|m|ss|s:这是一个选择(alternation)组,用竖线 | 分隔了多个模式。它表示我们要匹配的内容有多个可能的格式,这些格式代表了日期和时间的各个部分
/\b
yyyy|yy|MM|M|dd|d|HH|H|mm|m|ss|s
\b/g

\b 例子

例如,在正则表达式 \bword\b 中,\b 会匹配 "word" 这个单词的边界,确保它不是其他字符的一部分,而是一个完整的单词。

format 函数的执行

本质上2步: 

  1. 所需要的 map 的动态构造
  2. replace 的逐个取值
replace 函数逐个取得 matches 里的值
第2段的值
最终的值从可以从动态构造的map 里取得

兼容性

早期的 Safari 不兼容此种格式,目前已经ok了。

早期的会出现 Invalid date

参考: https://stackoverflow.com/questions/4310953/invalid-date-in-safari

console.log (new Date('2011-04-12'.replace(/-/g, "/")));

参考