JS-通过正则将Date转换为YYYY-MM-DD

1,083 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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

微信截图_20220728113213.png 可以看到,已经将字符串中所有的/匹配出来了。

月份和日期

月份和日期都是数字,所以可以确定使用\d进行匹配,又因为只需要匹配月份和日期为单个数字的情况即可,所以不用加上*或者+

然后就是确定月份和日期的位置,可以很明显的确定数字在/之后,所以正则表达式为:

const reg = /(?<=\/)\d/g

微信截图_20220728113718.png 可以看到,匹配了月份的7和日期的2,显然,并不需要匹配日期的2, 因为28已经符合需求了。

问题就在于,虽然上面的正则表达式只匹配了一个数字,但是并没有限制数字后面不可继续跟上数字,所以,需要在加上一一个限制即可,限制所匹配的数字在/或者空格之前:

const reg = /((?<=\/)\d(?=\/|\s))/g

微信截图_20220728114155.png 可以看到,这回就只是匹配的月份的7而已,不会匹配日期的2

完整正则表达式

const reg = /(\/)|((?<=\/)\d(?=\/|\s))/g

微信截图_20220728114347.png 已经能够匹配到全部的/和单个数字的月份。

字符处理

处理也是比较简单,将匹配到字符进行判断,如果是/,则替换为-,如果是数字,则补零。

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
}