源码地址

https://github.com/date-fns/date-fns

简介

借用官方的描述就是

date-fns,一个现代 JavaScript 日期实用程序库。date-fns 提供了最全面,最简单和一致的工具集,用于在浏览器和 Node.js 中操作 JavaScript 日期。

简写 export

export { default as add } from './add/index.js'

export { default as addBusinessDays } from './addBusinessDays/index.js'

export { default as addDays } from './addDays/index.js'

export { default as addHours } from './addHours/index.js'

首先看下index.js,意外发现一个简写的方法
如果你不是引用,仅仅只是将模块再暴露出去
是一个很好的简写方式
不需要每次

import HelloWord from './HelloWord.js';
export {HelloWord}

直接一行代码搞定

export { default as HelloWord } from './HelloWord.js'

他是怎么接受那么多种参数

说到时间格式化,我们经常会有种疑问,
问什么他能接受那么多种参数,而且返回值都是我想要的,这也太方便了吧。
来看个例子

import {format} from 'date-fns';
format(new  Date(2014, 1, 11), 'MM/dd/yyyy')//=> '02/11/2014'

这样也行

import {format} from 'date-fns';
format(1392048000000, 'MM/dd/yyyy')//=> '02/11/2014'

好了,看下他的实现方式吧
可以说,很棒
首先他封装了一个叫requiredArgs的函数
用于判断参数的个数,是否满足需求
不满足就直接抛错

export default function requiredArgs(required, args) {
    if (args.length < required) {
        throw new TypeError(
            required + ' argument' + required \> 1
                ? 's'
                : '' + ' required, but only ' + args.length + ' present'
            )
    }
}

再通过

Object.prototype.toString.call(argument)

判断类型
最后进行一个数据的格式化传递

判断数据类型 Object.prototype.toString.call

date-fns 的格式校验更严谨

  • 数字
var argStr = Object.prototype.toString.call(argument);
typeof argument === 'number' || argStr === '[object Number]'
  • Date
var argStr = Object.prototype.toString.call(argument);
argument instanceof Date || typeof argument === 'object' && argStr === '[object Date]'
  • 字符串
var argStr = Object.prototype.toString.call(argument);
typeof  argument  ===  'string'  ||  argStr  ===  '[object String]')

format

用一个简单的例子来说一下吧

第一步 正则格式化
/P+p+|P+|p+|''|'(''|[^'])+('|$)|./g
formatStr.match(longFormattingTokensRegExp)

通过上面这段正则,将数据转成一个数组

'MM/dd/yyyy'
   |
   |
["M", "M", "/", "d", "d", "/", "y", "y", "y", "y"]

我们顺便来看看这段正则代表什么意思
推荐大家一个好用的网站http://www.regexper.com/,专门看正则表达式的,需要翻墙,如果没有vpn,也可以去他的github,自己部署一个

image
上图就是好用的网站给我们分析出来的
从图中可以看出,这个
分为几组类型

  • 任意字符:中文,英文字母,/等特殊字符
  • 由‘’包含的字符
  • 空字符
  • p,pppp……
  • P,Pppp……
  • P,PPPP……

为什么要把P,p单独分开呢,因为在date-fns中P和p代表的格式类型较为丰富
如下图

p --->        12:00 AM 
pp --->       12:00:00 AM                      
ppp --->      12:00:00 AM GMT+2 
pppp --->     12:00:00 AM GMT+02:00 
Pp --->       05/29/1453, 12:00 AM             
PPpp --->     May 29, 1453, 12:00:00 AM        
PPPppp --->   May 29th, 1453 at ...            
PPPPpppp ---> Sunday, May 29th, 1453 at ...

接着往下说
他在得到上述数组后,会对P及p单独做一个格式化处理
其实这个格式化的过程,也是单单为了兼容p和P而做的
为了兼容各种语言

import zhCN from 'date-fns/locale/zh-CN';

const c = format(new Date(2014, 1, 11), 'p', {locale: zhCN});
//02/11/2014 上午 12:00

const c = format(new Date(2014, 1, 11), 'p', {locale: zhCN});
// 02/11/2014 12:00 AM
第二步 又格式化
["M", "M", "/", "d", "d", "/", "y", "y", "y", "y"]

目前已经得到了这么个格式的数据
因为仅仅是为了P和p的格式化考虑
又将数组重组字符串
再一次格式化
这次的正则,就很明显了

/[yYQqMLwIdDecihHKkms]o|(\w)\1*|''|'(''|[^'])+('|$)|./g

全都是你所熟悉的
我们来看看经过这次格式化,我们得到了什么,想分析下正则的巧妙,可以用第一个办法

["MM", "/", "dd", "/", "yyyy"]
第三步 对象函数

看到这里就很简单了
我们主要写好对应的方法
比如

M:  获取 非补0策略的 月份 函数
MM: 获取 补0策略的 月份 函数
dd: 获取 补0策略的 天数 函数
……

然后就行循环调用合并就搞定啦!
非常巧妙的正则使用。

扩展 flow.js

date-fns 中使用到了这个工具
有兴趣的小伙伴可以了解下
只要作用是把js的弱语言特性变强,严格变量数据类型

附 一个我觉得还可以介绍flow.js的地址https://www.jianshu.com/p/d21d4524a134


鱼叔子
95 声望0 粉丝