JavaScript 编写Date 格式化方法『Python风格ヾ(•ω•`)o』

Posted XianZhe_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript 编写Date 格式化方法『Python风格ヾ(•ω•`)o』相关的知识,希望对你有一定的参考价值。

javascript 编写Date日期格式化方法『Python风格ヾ(•ω•`)o』


一、Python 与 JavaScript 日期格式化对比🥯

在学习编写JS脚本的时候,一直觉得JS中的Date对象对于日期格式化方法很不友善,完全没有Python那么方便,我就在想能不能自己编写一个类似 Python风格的日期格式化方法,于是这篇笔记就此诞生

先来看看,在输出一样的时间格式的情况下,Python和JS的写法各是怎么样的

以显示 「年/月/日 时:分:秒」格式为例

  • Python 中输出指定格式日期

    可以看到,Python 对日期格式化处理是真的简洁且不失简单

    import time
    date = time.strftime(r"%Y/%m/%d %H:%M:%S", time.localtime())
    print(date)
    
    2021/06/01 23:41:03
    

    甚至还能够简写 time.strftime(r"%Y/%m/%d %H:%M:%S")

  • JS 中输出指定格式日期

    最能直接发现的是,相对于 Python 来说,JavaScript 对日期格式化处理就显得些许复杂且麻烦
    在制作成期望的日期格式时,需要预先将所需日期数据获取或计算,最后再进行拼接,才能实现日期格式化

    var nowDate = new Date();
    
    var year = nowDate.getFullYear();       // 获取年份
    var month = nowDate.getMonth() + 1;     // 获取月份
    var day = nowDate.getDate();            // 获取当前月内的天数
    var hour = nowDate.getHours();          // 获取小时 24小时制
    var minute = nowDate.getMinutes();      // 获取分钟
    var second = nowDate.getSeconds();      // 获取秒数
    
    console.log(`${year}/${month}/${day} ${hour}:${minute}:${second}`);
    

    在这里插入图片描述


二、使用JavaScript Moment 库

Moment.js1 在处理时间方面上是一个常用的轻量级 JavaScript 日期时间库,在 JavaScript 中解析,验证,操作和显示日期和时间,提供了比 JavaScript Date 对象 更强大的日期格式化功能,支持多种语言,可以任意新增一种新的语言包。

Moment 日期格式对应
类型Moment 格式对应Moment 格式对应
月份M1 2 … 11 12Mo1st 2nd … 11th 12th
月份MM01 02 … 11 12MMMJan Feb … Nov Dec
MMMMJanuary February … November December
季度Q1 2 3 4Qo1st 2nd 3rd 4th
月份的日期D1 2 … 30 31Do1st 2nd … 30th 31st
DD01 02 … 30 31
年份的日期DDD1 2 … 364 365DDDo1st 2nd … 364th 365th
DDDD001 002 … 364 365
星期几d0 1 … 5 6do0th 1st … 5th 6th
ddSu Mo … Fr SadddSun Mon … Fri Sat
ddddSunday Monday … Friday Saturday
星期几(语言环境)e0 1 … 5 6
星期几(ISO)E1 2 … 6 7
年份的星期w1 2 … 52 53wo1st 2nd … 52nd 53rd
ww01 02 … 52 53
年份的星期(ISO)W1 2 … 52 53Wo1st 2nd … 52nd 53rd
WW01 02 … 52 53
年份YY70 71 … 29 30YYYY1970 1971 … 2029 2030
Y1970 1971 … 9999 10000 10001
周年gg70 71 … 29 30gggg1970 1971 … 2029 2030
周年(ISO)GG70 71 … 29 30GGGG1970 1971 … 2029 2030
子午线AAM PMaam pm
小时H0 1 … 22 23HH00 01 … 22 23
h1 2 … 11 12hh01 02 … 11 12
k1 2 … 23 24kk01 02 … 23 24
分钟m0 1 … 58 59mm00 01 … 58 59
秒数s0 1 … 58 59ss00 01 … 58 59
小数秒钟S0 1 … 8 9SS00 01 … 98 99
SSS000 001 … 998 999SSSS … SSSSSSSSS000[0…] 001[0…] … 998[0…] 999[0…]
时区Z-07:00 -06:00 … +06:00 +07:00ZZ-0700 -0600 … +0600 +0700
Unix 时间戳X1360013296
Unix 毫秒时间戳x1360013296123

先在 Moment1 官网上下载并且导入 Moment.js 库

<script type="text/javascript" src="js/moment-with-locales.js"></script>

还是以显示 「年/月/日 时:分:秒」 格式为例

moment.locale("zh-cn");
var now = moment().format("YYYY/M/DD HH:mm:ss");
console.log(now);

在这里插入图片描述


三、编写函数实现格式化

虽然前面提到了 有 Moment.js 这个库已经实现了 日期格式化功能,但我们也可以自己去编写一个属于自己的日期格式化函数,对于简单的日期格式化类型,这并非什么难事

1)、思路:🤔
其实思路很简单,无非就是将获取需要日期格式的过程封装到函数里,并间格式化后的结果返回即可

function getFormatTime(date) {
    /* 获取需要的时间格式 */
    var year = date.getFullYear();       // 获取年份
    var month = date.getMonth() + 1;     // 获取月份
    var day = date.getDate();            // 获取当前月内的天数
    var hour = date.getHours();          // 获取小时 24小时制
    var minute = date.getMinutes();      // 获取分钟
    var second = date.getSeconds();      // 获取秒数
    /* 返回指定格式日期 */
    return `${year}/${month}/${day} ${hour}:${minute}:${second}`;
}

var now = new Date();

console.log(getFormatTime(now));

2)、优缺点:

  • 很明显的缺点是,每次函数所返回的日期格式是固定的,如果需要另外的日期格式,则需要再写多一个函数,或是修改函数内部代码
  • 优点还是有的,一定程度上增加了代码复用,相较 「一、Python 与 JavaScript 日期格式化对比🥯」 中的 JS 示例减少了部分冗余,但还不如正统的日期格式化来的直接方便
  • 但对于固定单一的时间显示要求,此方法写法简单也是可以的

四、为JavaScript Date对象添加格式化方法👺

终于来到本文的重点,为JavaScript Date对象添加格式化方法

1)、思路:🤔

日期格式化的格式内容,无非就是一堆字符串,只需要提取这个字符串中符合格式要求的内容,并将其替换成对应的日期时间数据即可。
可以使用正则去匹配格式是否存在,再将匹配的格式内容进行替换操作,从而实现基本的日期格式化功能,剩下的只是支持什么样的日期格式化,以及程序的扩展性。

与标题一致,我将使用Python风格的日期匹配格式进行编写


2)、分钟和秒数 两位数标准化

因为在 Date 对象获取 分钟和秒数 的时候返回的内容在 0 - 9 之间时,前面并不带一个0,比如 05分,那就需要对其进行一个两位数的标准化,将其标准化的过程十分简单

/* 两位数标准化函数 */
function getNormal(time) {
    // 使用正则判断是否为一位数数字
    if (/^\\d$/.test(time)) {
        return `0${time}`
    } else {
        return time
    }
}


/* 分钟、秒钟 */
var now = new Date();
var second = now.getSeconds();
var minute = now.getMinutes();
console.log(getNormal(second));
console.log(getNormal(minute));

在这里插入图片描述

3)、如何去使用正则匹配替换:

还是以 「一、Python 与 JavaScript 日期格式化对比🥯」 中的日期格式为准,「年/月/日 时:分:秒」

Date.prototype.toFormat = function (text) {
    function getNormal(time) {
        // 使用正则判断是否为一位数数字
        if (/^\\d$/.test(time)) {
            return `0${time}`
        } else {
            return time
        }
    }

    var format = {
        "%Y": String(this.getFullYear()),
        "%m": String(this.getMonth() + 1),
        "%d": String(this.getDate()),
        "%H": String(this.getHours()),
        "%I": String(this.getHours() % 12),
        "%M": getNormal(this.getMinutes()),
        "%S": getNormal(this.getSeconds()),
        "%%": "%"
    }

    for (var i in format) {
        if (RegExp(`(${i})`).test(text)) {
            text = text.replace(RegExp.$1, format[i]);
        }
    }
    return text
}

var now = new Date();
console.log(now.toFormat("%Y/%m/%d %H:%M:%S"))

你以为就这样结束了?那还是太年轻,当使用多次相同的日期格式,那就会发现一个BUG,同一种日期格式只能被匹配从左往右的第一个

var now = new Date();
console.log(now.toFormat("%Y/%m/%d %Y-%Y-%m %H:%M:%S"))

在这里插入图片描述

标准的日期格式化,都是全局匹配的,不可能单单只匹配一个这么简单,那么要怎么才能实现全局匹配呢?还得使用到正则

Date.prototype.toFormat = function (text) {
    function getNormal(time) {
        // 使用正则判断是否为一位数数字
        if (/^\\d$/.test(time)) {
            return `0${time}`
        } else {
            return time
        }
    }

    var format = {
        "%Y": String(this.getFullYear()),
        "%m": String(this.getMonth() + 1),
        "%d": String(this.getDate()),
        "%H": String(this.getHours()),
        "%I": String(this.getHours() % 12),
        "%M": getNormal(this.getMinutes()),
        "%S": getNormal(this.getSeconds()),
        "%%": "%"
    }

    for (var i in format) {
        if (RegExp(`(${i})`).test(text)) {
            // 使用全局替换模式
            var target = new RegExp(RegExp.$1, "g");
            text = text.replace(target, format[i]);
        }
    }
    return text
}

再使用多次相同的日期格式时,就能够被成功匹配了

var now = new Date();
console.log(now.toFormat("%Y/%m/%d %Y-%Y-%m %H:%M:%S"))

在这里插入图片描述

4)、JS Date对象能够获取什么日期数据

需要注意的是,在一些方法返回的内容需要进行处理才能使用,比如说获取月份的 getMonth() 返回的范围是 0~11,这就意味如果放到网页中显示的话,就需要我们对返回内容进行 +1 操作

Data对象获取日期方法
Data 对象方法对应
getFullYear()以四位数字返回年份
getMonth()返回月份 (0 ~ 11)
getDate()返回一个月中的某一天 (1 ~ 31)
getDay()返回一周中的某一天 (0 ~ 6)
getHours()返回小时 (0 ~ 23)
getMinutes()返回分钟 (0 ~ 59)
getSeconds()返回秒数 (0 ~ 59)
getMilliseconds()返回毫秒(0 ~ 999)
getTime()返回 1970 年 1 月 1 日至今的毫秒数
getUTCFullYear()根据世界时间 以四位数的年份返回年份
getUTCMonth()根据世界时间 返回月份 (0 ~ 11)
getUTCDate()根据世界时间 返回一个月中的某一天 (1 ~ 31)
getUTCDay()根据世界时间 返回一周中的某一天 (0 ~ 6)
getUTCHours()根据世界时间 返回小时 (0 ~ 23)
getUTCMinutes()根据世界时间 返回分钟 (0 ~ 59)
getUTCSeconds()根据世界时间 返回秒数 (0 ~ 59)
getUTCMilliseconds()根据世界时间 返回毫秒(0 ~ 999)

5)、如何实现多种日期格式

在开始这个步骤前,可以打开Python time标准库官方手册或相关博客教程,去对照一下Python 都支持哪些日期格式化的格式

这里展示部分使用到的 Python 日期格式支持

Python 格式对应Python 格式对应
%y两位数的年份表示%Y四位数的年份表示
%m月份%d天数
%H24小时制小时数%I12小时制小时数
%M分钟数%S秒数
%A本地完整星期名%B本地完整月份名
%w星期(数值为0-6,星期天每为星期的开始)%%%号本身

完整代码

Date.prototype.toFormat = function (text) {
    var weekdays = {
        0: "Sunday",
        1: "Monday",
        2: "Tuesday",
        3: "Wednesday",
        4: "Thursday",
        5: "Friday",
        6: "Saturday"
    };
    var weekdaysShort = {
        0: "Sun",
        1: "Mon",
        2: "Tue",
        3: "Wed",
        4: "Thu",
        5: "Fri",
        6: "Sat"
    };
    var months = {
        0: "January",
        1: "February",
        2: "March",
        3: "April",
        4: "May",
        5: "June",
        6: "July",
        7: "August",
        8: "September",
        9: "October",
        10: "November",
        11: "December"
    };
    var monthsShort = {
        0: "Jan",
        1: "Feb",
        2: "Mar",
        3: "Apr",
        4: "May",
        5: "Jun",
        6: "Jul",
        7: "Aug",
        8: "Sep",
        9: "Oct",
        10: "Nov",
        11: "Dec"
    };

    function getNormal(Time) {
        if (/^\\d$/.test(Time)) {
            return `0${Time}`
        } else {
            return Time
        }
    }

    var format = {
        "%y": this.getFullYear().toString().substr(2),
        "%Y": String(this.getFullYear()),
        "%m": String(this.getMonth() + 1),
        "%d": String(this.getDate()),
        "%w": String(this.getDay()),
        "%H": String(this.getHours()),
        "%I": String(this.getHours() % 12),
        "%M": getNormal(this.getMinutes()),
        "%S": getNormal(this.getSeconds()),
        "%a": weekdaysShort[this.getDay()],
        "%A": weekdays[this.getDay()],
        "%b": monthsShort[this.getMonth()],
        "%B": months[this.getMonth()],
        "%%": "%"
    }

    for (var i in format) {
        if (RegExp(`(${i})`).test(text)) {
            // 使用全局替换模式
            var target = new RegExp以上是关于JavaScript 编写Date 格式化方法『Python风格ヾ(•ω•`)o』的主要内容,如果未能解决你的问题,请参考以下文章

javascript中的Date和java语言中的Date能互相转换么,能的话该怎么转?谢谢

javascript-封装Date日期类

javascript Date format(js日期格式化)

javascript Date format(js日期格式化) (转)

javascript Date format(js日期格式化)

javascript Date format(js日期格式化)