携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
前言
日常开发中,通过使用new Date()去获取时间,然后在通过各种手段将时间转换成开发需求中的格式,
通常是YYYY-MM-DD HH:mm:ss。
然而,JS中并没有直接提供一个函数可以将时间转换为YYYY-MM-DD HH:mm:ss。
唯一一个比较接近的是toLocaleString(),它会将时间转换成如下格式:
let date = (new Date()).toLocaleString()
console.log('date:', date)
// output: date: 2022/7/28 11:15:02
可以看到,时间格式与HH:mmLss一致,但是日期格式与YYYY-MM-DD不同,主要月和日不会自动补零,以及年月日之间使用的/。
所以,程序员通常会逐个获取年月日,然后手动补零,再使用-拼接到一起:
const d = new Date();
const year = d.getFullYear();
let month = d.getMonth() + 1;
month = month < 10 ? "0" + month : month;
let day = d.getDate();
daty = day < 10 ? '0' + day : day;
console.log(year+'-'+month+'-'+day);
这种方法简单直接,但比较繁琐,不够简洁高效。
于是乎,尝试使用正则来解决。
思路
首先,将Date对象转换为字符串,而toLocaleString()转换成字符串之后格式与YYYY-MM-DD HH:mm:ss最为接近。
然后使用正则表达式将字符串中/与单个数字的月份和日期匹配出来,进行特殊处理。
正则表达式
/
首先,匹配/字符,直接使用\/就可以匹配,所以正则如下:
const reg = /(\/)/g
可以看到,已经将字符串中所有的
/匹配出来了。
月份和日期
月份和日期都是数字,所以可以确定使用\d进行匹配,又因为只需要匹配月份和日期为单个数字的情况即可,所以不用加上*或者+。
然后就是确定月份和日期的位置,可以很明显的确定数字在/之后,所以正则表达式为:
const reg = /(?<=\/)\d/g
可以看到,匹配了月份的
7和日期的2,显然,并不需要匹配日期的2,
因为28已经符合需求了。
问题就在于,虽然上面的正则表达式只匹配了一个数字,但是并没有限制数字后面不可继续跟上数字,所以,需要在加上一一个限制即可,限制所匹配的数字在/或者空格之前:
const reg = /((?<=\/)\d(?=\/|\s))/g
可以看到,这回就只是匹配的月份的
7而已,不会匹配日期的2。
完整正则表达式
const reg = /(\/)|((?<=\/)\d(?=\/|\s))/g
已经能够匹配到全部的
/和单个数字的月份。
字符处理
处理也是比较简单,将匹配到字符进行判断,如果是/,则替换为-,如果是数字,则补零。
date = date.replace(reg, $1 => $1 === '/' ? '-' : 0 + $1)
完整代码
/**
* @param { String | Date } date
*/
function formatDateToYYYYMMDD (date) {
const reg = /(\/)|((?<=\/)\d(?=\/|\s))/g
Object.prototype.toString.call(date) === '[object Date]' && (date = date.toLocaleString())
typeof date === 'string' && (date = date.replace(reg, $1 => $1 === '/' ? '-' : 0 + $1))
return date
}