title: Date时间格式化
date: 2021-06-09
description: 这是可以用于项目开发中的时间格式化实践
开始
我们经常在项目中看到Date
转换成相关的时间展示,
比如2021年06月20日
、2021-06-20
、2021年06月20日 18:00:00
本文将介绍如何快速、方便的让Date
对象转换成上述的格式
常规操作
const date = new Date();
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const hour = date.getHours();
const minute = date.getMinutes();
const second = date.getSeconds();
//2021年06月20日
console.log(year + '年' + month + '月' + day + '日' )
//2021年06月20日 18:00:00
console.log(year + '年' + month + '月' + day + '日' + hour+ ':' + minute +':' + second)
上面的方式好处就是足够灵活,可以按照需求任意搭配,不好的地方也有:
1、代码太过于冗长,使用不太友好
2、要是存在多个时间,变量命名容易冲突
3、不方便复用、移植、重构
如何改善
1、针对上面的问题,我们可以通过function
来简化整个操作
在js里面,function
可以利用他的作用域有效隔离变量命名冲突,
在const
、let
之前还可以通过闭包来实现作用域隔离
2、定义规则,利用正则匹配相关规则实现内容替换,通过字符串的replace
来替换上述console
的组合操作
3、挂载在Date
对象的prototype
上面,可以对整个Date
对象实现方法扩展,方便复用
定义规则
输入 | 示例 | 描述 |
---|---|---|
yyyy |
2020 |
输入几个y 就是几位数字的年份 |
M MM |
7 07 |
月份数字,复数的M 当小于10则会追加0 |
d dd |
3 03 |
月的某天,复数的d 当小于10则会追加0 |
H HH |
0..23 |
小时(24小时制),复数的h 当小于10则会追加0 |
h hh |
1..12 |
小时(12小时制),复数的h 当小于10则会追加0 |
m mm |
0..59 |
分钟,复数的m 当小于10则会追加0 |
s ss |
0..59 |
秒数,复数的s 当小于10则会追加0 |
S SS SSS |
0..999 |
带分数的秒钟,复数的S 当小于10则会追加0 |
w ww |
1..7 |
指定日期的星期中的第几天,复数的w 当小于10则会追加0 |
W |
一..天 |
指定日期的星期中的第几天,汉字一 二 三 四 五 六 天 |
q |
1..4 |
季度 |
如何调用
我们在尝试在Date
对象上面挂载一个format
方法,通过这个方法,传入上面定义的规则实现格式的转换
//定义方法
Date.prototype.format = function(rule){
console.log(this)
return rule
}
//方法调用
new Date().format('yyyy-MM-dd HH:mm:ss')
问题:
1.定义在prototype
上面是为什么
2.function
的声明可不可以使用箭头函数替代
如何转换
上面已经将方法定义好,调用方式也确定了,我们将使用正则去匹配相关的Rule
,并生成文本
替换规则:
1、找出相同的规律,建立规则映射结构
2、年份需要单独处理
3、带分数的秒钟需要单独处理
4、汉化的周几需要单独处理
规则1:
通过示例可以看出,大部分的值都是在两位数之内,同时传入复数的规则都会追加0
我们利用正则匹配区间内$n
的特性可以获得对应的匹配字符串
string.substring
可以实现复数规则追加0
规则2:
年份数值不需要复数规则追加0
,传入几个y
则展示多少位年份
所以这里要提出来单独处理
规则3:
带分数的秒钟这里的值是三位数字的,和两位数字的处理在string.substring
有所不同
所以这里也要提出来单独处理
规则4:
汉化的周几,这里需要建立一个数值映射结构{1: "一",2: "二",3: "三",4: "四",5: "五",6: "六",0: "天"}
所以这里也要提出来单独处理
综上所述,我们用代码实现下面的format
函数
Date.prototype.format = function(ruleText){
const date = {
"M+": this.getMonth() + 1,
"d+": this.getDate(),
"H+": this.getHours(),
"h+": (this.getHours() + 1) % 12 || 12,
"m+": this.getMinutes(),
"s+": this.getSeconds(),
"q+": Math.floor((this.getMonth() + 3) / 3),
"w+": this.getDay()
};
if (/(y+)/i.test(ruleText)) {
ruleText = ruleText.replace(
RegExp.$1,
(this.getFullYear() + "").substring(4 - RegExp.$1.length)
);
}
if (/(S+)/.test(ruleText)) {
const ms = this.getMilliseconds();
ruleText = ruleText.replace(
RegExp.$1,
RegExp.$1.length === 1
? ms
: ("000" + ms).substring(("" + ms).length)
);
}
if (/(W+)/.test(ruleText)) {
const weeks = {1: "一",2: "二",3: "三",4: "四",5: "五",6: "六",0: "天"};
ruleText = ruleText.replace(RegExp.$1, weeks[date["w+"]]);
}
for (const k in date) {
if (new RegExp("(" + k + ")").test(ruleText)) {
ruleText = ruleText.replace(
RegExp.$1,
RegExp.$1.length === 1
? date[k]
: ("00" + date[k]).substring(("" + date[k]).length)
);
}
}
return ruleText;
}
//测试
new Date().format("测试1=>yyyy年MM月dd日 hh:mm:ss 星期W Qq")
new Date().format("测试2=>yyyy年MM月dd日 HH:mm:ss 星期W Qq")
new Date().format("测试3=>yyyy年MM月d日 H:mm:ss 星期W Qq")
new Date().format("测试3=>yy年M月d日 H:mm:ss 星期W Qq")
运行上面的测试代码,获得如下结果
问题:
1.如果传入yyyyyy
会发生什么,其他的规则呢
2.针对这个方法还有优化的点吗
总结
1、解决Date
时间格式化,在项目中反复的去按照需求规则展示时间的代码冗余
2、将规则语义化,更利于展示和理解
3、可移植性强,能多项目复用,对项目不会产生其余的副作用
至此,整个Date
时间格式化函数就完成了