在 关于Date对象那些事 一文中的第一节,我们就给出了转换日期指定格式的方法。
但是这个方法中,有些地方对于初学者可能有点费解,尤其是正则部分。此处对其做个详解。
1. 获取当前日期
获取当前日期时间,我们知道通过方法 new Date()
就可以得到,但是获取到是一个标准格式时间 Fri Jan 18 2019 13:56:47 GMT+0800 (中国标准时间)
。但通常我们更渴望得到 2019-01-18 13:56:47
或者 2019/01/18 13:56:47
这种格式。
var d = new Date(); // 获取当前时间
console.log(d); // Fri Jan 18 2019 14:00:01 GMT+0800 (中国标准时间)
console.log(typeof d); // "object"
2.获取特定格式的日期猜想
想要通过截取标准格式时间是不太理想的,因为那是一个对象,不好进行字符串操作。即使转串后可以截取到,但总不太靠谱。于是,我们就想通过Data内置对象方法,把年、月、日、小时、分钟、秒,一一取出来,然后做拼接。
var yy = d.getFullYear(); // 年
var mm = d.getMonth() + 1; // 月
var dd = d.getDate(); // 日
var hh = d.getHours(); // 小时
var min = d.getMinutes(); // 分钟
var ss = d.getSeconds(); // 秒
var qq = Math.floor((d.getMonth() + 3) / 3); // 季度
var sss = d.getMilliseconds(); // 毫秒
console.log("当前时间是:",yy + "-" + mm + "-" + dd + " " + hh + ":" + min + ":" + ss); // 当前时间是: 2019-1-dd 14:10:21
console.log("当前季度是:",qq); // 当前季度是: 1
console.log("当前毫秒数是:",sss); // 当前毫秒数是: 366
注意:getMonth()
返回的范围是0-11,所以需要累加1.
我们把这个方法封装成一个函数:
/**
* formatDate
* @return {string}
*/
function formatDate(){
var yy = d.getFullYear(); // 年
var mm = d.getMonth() + 1; // 月。
var dd = d.getDate(); // 日
var hh = d.getHours(); // 小时
var min = d.getMinutes(); // 分钟
var ss = d.getSeconds(); // 秒
var qq = Math.floor((d.getMonth() + 3) / 3); // 季度
var sss = d.getMilliseconds(); // 毫秒
return yy + "-" + mm + "-" + dd + " " + hh + ":" + min + ":" + ss);
}
// 调用方法
formatDate(); // 2019-1-dd 14:10:21
3. 最终方案及详解
上面的函数确实能重复调用了,但是不过灵活,复用性不强。我们希望能带入参数,用以说明想要指定的日期格式,然后返回对应的日期格式。
这就不得不用上正则相关方法。具体演练过程这里就不说明,我们直接分析下面方案的实现过程。
/**
* formatDate方法,将 Date 转化为指定格式的String
* @param {String} a 指定格式的字符串,例如 "yyyy-M-d h:m:s"
* @return {String} 匹配指定格式的日期时间字符串
* 说明:月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
* 例子:
* (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
* (new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
*/
function formatDate(a){
var d = new Date(); // 获取当前时间
// 构造对象o,里面存储当前时间对应的年、月、日、时、分、秒、季度、毫秒参数
var o = {
"M+": d.getMonth() + 1,
"d+": d.getDate(),
"h+": d.getHours(),
"m+": d.getMinutes(),
"s+": d.getSeconds(),
"q+": Math.floor((d.getMonth() + 3) / 3),
"S": d.getMilliseconds()
};
// 获取年份
if (/(y+)/.test(a)) a = a.replace(RegExp.$1, (d.getFullYear() + "").substr(4 - RegExp.$1.length));
// 获取其他
for (var k in o) {
if (new RegExp("(" + k + ")").test(a)) a = a.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
}
return a;
}
// 调用方法
console.log(formatDate("yyyy-M-d")); // 2019-1-18
代码说明:
- 获取年份部分:
(1)/(y+)/
是一个正则表达式,/(y+)/.test(a)
是判断参数a
中是否有一个或多个字符y
,若有,返回true。
(2)RegExp
是一个对象(函数对象),它是一个全局对象。RegExp.$1
是全局属性,当执行任意正则表达式匹配操作时,JavaScript会自动更新RegExp
上的全局属性。
补充说明:
- 关于
RegExp
对象以及它的静态属性$1
可以参考 MDN: RegExp.$1-$9 和 csdn: JavaScript RegExp.$1-$9 属性详解。 - 取子串方法语法:
substr(start, length)
4. 拓展
Date.prototype.Format = function(a) {
var o = {
"M+": this.getMonth() + 1,
"d+": this.getDate(),
"h+": this.getHours(),
"m+": this.getMinutes(),
"s+": this.getSeconds(),
"q+": Math.floor((this.getMonth() + 3) / 3),
"S": this.getMilliseconds()
};
if (/(y+)/.test(a)) a = a.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o) {
if (new RegExp("(" + k + ")").test(a)) a = a.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)))
}
return a
};
// 调用方法
console.log(new Date().Format("yy-MM-dd hh:mm:ss"));//19-01-18 15:04:30