3.5 日期的扩展与修复
Date构造器是JavaScript中传参形式最丰富的构造器,大致分为四种。
new Date(); new Date(value);//传入毫秒数 new Date(dateString); new Date(year, month, day /*, hour, minute, second, millisecond*/);
其中第三种可以玩N多花样,个人建议只使用“2009/07/12 12:34:56 ”,后面的时分秒可省略。这个所有浏览器都支持。此构造器的兼容列表可见此文:
http://dygraphs.com/date-formats.html
若要修正它的传参,这恐怕是个大工程,要整个对象替换掉,并且影响Object.prototype.toString的类型判定。因此不建议修正。es5.js中有相关源码,大家可以看这里:
https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js
JavaScript的日期是抄自Java的java.util.Date,但是Date这个类中的很多方法对时区等支持不够,且不少都是已过时,Java程序员也推荐使用calnedar类代替Date类。JavaScript可选择的余地比较少,只能捏着鼻子继续用。如对属性使用了前后矛盾的偏移量。月份与小时都是基于0,月份中的天数则是基于1,而年则是从1900开始的。
接着下来,我们为旧版本浏览器添加几个ecma262标准化的日期方法吧。
if (!Date.now) { Date.now = function() { return +new Date; } } if (!Date.prototype.toISOString) { void function() { function pad(number) { var r = String(number); if (r.length === 1) { r = '0' + r; } return r; } Date.prototype.toJSON = Date.prototype.toISOString = function() { return this.getUTCFullYear() + '-' + pad(this.getUTCMonth() + 1) + '-' + pad(this.getUTCDate()) + 'T' + pad(this.getUTCHours()) + ':' + pad(this.getUTCMinutes()) + ':' + pad(this.getUTCSeconds()) + '.' + String((this.getUTCMilliseconds() / 1000).toFixed(3)).slice(2, 5) + 'Z'; }; }(); }
IE6、IE7中,getYear、setYear方法存在BUG,这个修起来比较简单。
if ((new Date).getYear() > 1900) { Date.prototype.getYear = function() { return this.getFullYear() - 1900; }; Date.prototype.setYear = function(year) { return this.setFullYear(year); //+ 1900 }; }
至于扩展,由于涉及本地化的原因,外国许多日期库都需要改一改才能用,其中以 dataFormat这个很有用的方法为最。我先给一些常用的扩展吧。
传入两个Date类型的日期,求出它们相隔多少天。
var getDatePeriod = function(start, finish) { return Math.abs(start * 1 - finish * 1) / 60 / 60 / 1000 / 24; }
传入一个Date类型的日期,求出它所在月的第一天。
var getFirstDateInMonth = function(date) { return new Date(date.getFullYear(), date.getMonth(), 1); }
传入一个Date类型的日期,求出它所在月的最后一天。
var getLastDateInMonth = function(date) { return new Date(date.getFullYear(), date.getMonth() + 1, 0); }
传入一个Date类型的日期,求出它所在季度的第一天。
var getFirstDateInQuarter = function(date) { return new Date(date.getFullYear(), ~~(date.getMonth() / 3) * 3, 1); }
传入一个Date类型的日期,求出它所在季度的最后一天。
var getFirstDateInQuarter = function(date) { return new Date(date.getFullYear(), ~~(date.getMonth() / 3) * 3 + 3, 0); }
判断是否为闰年。
Date.prototype.isLeapYear = function() { return new Date(this.getFullYear(), 2, 0).getDate() == 29; }
取得当前月份的天数。
function getDaysInMonth1(date) { switch (date.getMonth()) { case 0: case 2: case 4: case 6: case 7: case 9: case 11: return 31; case 1: var y = date.getFullYear(); return y % 4 == 0 && y % 100 != 0 || y % 400 == 0 ? 29 : 28; default: return 30; } } function getDaysInMonth2(date) { switch (date.getMonth()) { case 0: case 2: case 4: case 6: case 7: case 9: case 11: return 31; case 1: var y = date.getFullYear(); return y % 4 == 0 && y % 100 != 0 || y % 400 == 0 ? 29 : 28; default: return 30; } } function getDaysInMonth3(date) { return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); }
最后是dateForamt方法,由于太长了,我也不便贴出来,可到以下链接查看:
https://github.com/RubyLouvre/mass-Framework/blob/1.41/avalon.js