实际上我曾经在我的Blog中谈到过这个功能(查看原文),但当时并未做详细的解释,代码亦写得比较拙劣,这段时间又翻起了这段代码,觉得还是有很大改进的余地,于是觉得把代码再行精简一下。
这次改进的主要有几个地方:
将日期表达式转换为取数字正则的代码,原来的代码写得非常之业余,我们可以对比一下两次代码:
原来的代码:
pattern = format.replace("yyyy", "(~1{4})").replace("yy", "(~1{2})")
.replace("MM", "(~1{2})").replace("M", "(~1{1,2})")
.replace("dd", "(~1{2})").replace("d", "(~1{1,2})").replace(/~1/g, "d");
新的代码:
pattern = format.replace(/(yyyy)/g, "([0-9]{4})")
.replace(/(yy)|(MM)|(dd)|(hh)|(mm)|(ss)/g, "([0-9]{2})")
.replace(/[Mdhms]/g, "([0-9]{1,2})");
对比这两次代码,后面的代码可读性更强,漂亮了许多。
把获取索引的代码进行了改进
var yPos = format.indexOf("yyyy");
var mPos = format.indexOf("MM");
var dPos = format.indexOf("dd");
var hPos = format.indexOf("hh");
var miPos = format.indexOf("mm");
var sPos = format.indexOf("ss");
if (mPos == -1) mPos = format.indexOf("M");
if (yPos == -1) yPos = format.indexOf("yy");
if (dPos == -1) dPos = format.indexOf("d");
if (hPos == -1) hPos = format.indexOf("h");
if (miPos == -1) miPos = format.indexOf("m");
if (sPos == -1) sPos = format.indexOf("s");
新的代码:
//获取子表达式的索引
getIndex = function(expr1, expr2) {
var index = format.indexOf(expr1);
if (index == -1) index = format.indexOf(expr2);
return index;
}
var yPos = getIndex("yyyy", "yy");
var mPos = getIndex("MM", "M");
var dPos = getIndex("dd", "d");
var hPos = getIndex("hh", "h");
var miPos = getIndex("mm", "m");
var sPos = getIndex("ss", "s");
新的代码进行了提取封装,可维护性更强
还有其它的改进就不说了,读者自己看,对比一下两者的差异。
最终新代码:
//将字符串转换为日期
String.prototype.toDate = function(format) {
pattern = format.replace(/(yyyy)/g, "([0-9]{4})")
.replace(/(yy)|(MM)|(dd)|(hh)|(mm)|(ss)/g, "([0-9]{2})")
.replace(/[Mdhms]/g, "([0-9]{1,2})");
//获取子表达式的索引
getIndex = function(expr1, expr2) {
var index = format.indexOf(expr1);
if (index == -1) index = format.indexOf(expr2);
return index;
}
var today = new Date();
var returnDate;
if (new RegExp(pattern).test(this)) {
var yPos = getIndex("yyyy", "yy");
var mPos = getIndex("MM", "M");
var dPos = getIndex("dd", "d");
var hPos = getIndex("hh", "h");
var miPos = getIndex("mm", "m");
var sPos = getIndex("ss", "s");
var data = { y: 0, m: 0, d: 0, h: 0, mi: 0, s: 0 };
//对索引进行排序
var pos = new Array(yPos + ",y", mPos + ",m", dPos + ",d", hPos +
",h", miPos + ",mi", sPos + ",s").sort(
function(a, b) {
a = parseInt(a.split(",")[0]);
b = parseInt(b.split(",")[0]);
return a > b;
}
);
//删除索引为-1的数组
var tmpIndex = 0;
var newPos = new Array();
for (var i = 0; i < pos.length; i++) {
if (parseInt(pos[i].split(",")[0]) != -1) {
newPos[tmpIndex] = pos[i];
tmpIndex++;
}
}
//与当前文本进行匹配
var m = this.match(pattern);
for (var i = 1; i < m.length; i++) {
if (i == 0) return;
var flag = newPos[i - 1].split(',')[1];
data[flag] = m[i];
};
data.y = data.y || today.getFullYear(); //年如果为空,则取当前年
data.d = data.d || today.getDate(); //天如果为空,则取今天
//月不需要处理,因为月的0月是1月
//如果年是yy格式,则加上20
if (data.y.toString().length == 2) data.y = parseInt('20' + data.y);
data.m -= 1;
returnDate = new Date(data.y, data.m, data.d, data.h, data.mi, data.s);
}
returnDate = returnDate || today;
return returnDate;
}
document.writeln("
<pre>测试结果");
document.writeln("10月18日2008年 10点11分12秒".toDate("MM月dd日yyyy年 hh点mm分ss秒"));
document.writeln("2008-10-8".toDate("yyyy-M-d")); //2008年10月8号
document.writeln("12-18 2008".toDate("MM-dd yyyy")); //2008年12月18号
document.writeln("12-16".toDate("MM-dd")); //2009年12月16号
document.writeln("</pre>");
旧代码:
//将字符串转换为日期
String.prototype.toDate = function(format) {
pattern = format.replace("yyyy", "(~1{4})").replace("yy", "(~1{2})") //年
.replace("MM", "(~1{2})").replace("M", "(~1{1,2})") //月
.replace("dd", "(~1{2})").replace("d", "(~1{1,2})") //日
.replace("hh", "(~1{2})").replace("h", "(~1{1,2})") //时
.replace("mm", "(~1{2})").replace("m", "(~1{1,2})") //分
.replace("ss", "(~1{2})").replace("s", "(~1{1,2})") //称
.replace(/~1/g, "d").replace(" ", "[s]");
sortDate = function(a, b) {
a = parseInt(a.split(",")[0]);
b = parseInt(b.split(",")[0]);
return a > b;
}
var returnDate;
if (new RegExp(pattern).test(this)) {
var yPos = format.indexOf("yyyy");
var mPos = format.indexOf("MM");
var dPos = format.indexOf("dd");
var hPos = format.indexOf("hh");
var miPos = format.indexOf("mm");
var sPos = format.indexOf("ss");
if (mPos == -1) mPos = format.indexOf("M");
if (yPos == -1) yPos = format.indexOf("yy");
if (dPos == -1) dPos = format.indexOf("d");
if (hPos == -1) hPos = format.indexOf("h");
if (miPos == -1) miPos = format.indexOf("m");
if (sPos == -1) sPos = format.indexOf("s");
var pos = new Array(yPos + ",y", mPos + ",m", dPos + ",d", hPos +
",h", miPos + ",mi", sPos + ",s").sort(sortDate);
var tmpIndex = 0;
for (var i = 0; i < pos.length; i++) {
if (pos[i].indexOf('-1') < 0) break;
tmpIndex++;
}
pos = pos.splice(tmpIndex, pos.length - tmpIndex);
var data = { y: 0, m: 0, d: 0, h: 0, mi: 0, s: 0 };
var m = this.match(pattern);
for (var i = 1; i < m.length; i++) {
if (i == 0) return;
var flag = pos[i - 1].split(',')[1];
data[flag] = m[i];
};
if (data.y.toString().length == 2) {
data.y = parseInt('20' + data.y);
}
data.m = data.m - 1;
returnDate = new Date(data.y, data.m, data.d, data.h, data.mi, data.s);
}
if (returnDate == null || isNaN(returnDate)) returnDate = new Date();
return returnDate;
}