javascript Date format 时间格式化


title: Date时间格式化
date: 2021-06-09
description: 这是可以用于项目开发中的时间格式化实践


开始

我们经常在项目中看到Date转换成相关的时间展示,
比如2021年06月20日2021-06-202021年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可以利用他的作用域有效隔离变量命名冲突,
constlet之前还可以通过闭包来实现作用域隔离

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")

运行上面的测试代码,获得如下结果


res1.png

问题:
1.如果传入yyyyyy会发生什么,其他的规则呢
2.针对这个方法还有优化的点吗

总结

1、解决Date时间格式化,在项目中反复的去按照需求规则展示时间的代码冗余
2、将规则语义化,更利于展示和理解
3、可移植性强,能多项目复用,对项目不会产生其余的副作用
至此,整个Date时间格式化函数就完成了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容