【分享】警惕你的 Date 对象

WebAdvocate 2010-07-07 04:46:01
日子一天天过去,像时钟的表针一样摇曳着时光,很难想象没有时间的日子要怎样面对,又很讨厌生活在一分一秒的时间的格子里,人真是个矛盾的动物……
分分秒秒,我们都跟时间有密切的接触。也因此,很多程序中,也少不了对时间的处理。
这本来已经很复杂,可是,这么多的浏览器厂商还是没能给我们一个简单的环境。
还是那句话,生命不止,浏览器兼容性问题不歇。
今天,就说一下,跟时间有密切关系的

JS 内置对象 Date

Date对象在JS里应该是比较常用的对象了,属于Native Object(相对于 Host Object,即,宿主对象,例如,document)。
关于这个对象比较官方的说法在 ECMA-262 5th 的第 15.9 中,有兴趣的童鞋可以看看。
这个对象提供了好多比较实用的方法,但奈何有些方法在各浏览器中的实现是不同的。千里之堤,溃于蚁穴,往往一个小小的失误,会造成致命的问题。为了程序的健壮性,我们应该去认识这些差异性,以做到未雨绸缪,有效的规避这些错误。
那么,现在就说说常见的几个错误。

toLocaleString()的兼容性问题

根据 ECMA-262 5th中的说明,这个方法应该返回一个字符串的值,以合适的易读的方式,来显示当前时区的日期。具体没有规定显示成什么样子。
于是乎,差异就产生了。
看例子:
document.write((new Date("1999/09/09")).toLocaleString());

各浏览器中的结果:
Firefox 和 IE : 1999年9月9日 0:00:00
Opera: 1999/9/9 0:00:00
Safari: Thursday, September 09, 1999 00:00:00
Chrome : Thu Sep 09 1999 00:00:00 GMT+0800 (China Standard Time)

如果,你一直认为,它的返回值是 “1999年9月9日 0:00:00”,并且按照它来处理,那么,你的程序逻辑,肯定会出问题。如果是比较基础的底层的方法,那么,可能会影响大功能。

关于日期的显示,可以使用自己的方法,来消除这种差异。以下程序健壮性不好,是那么个意思。

/**
* date : Date 对象实例
*/
function localeDate(date) {
return date.getFullYear()+ "年"
+ (date.getMonth()+ 1) + "月"
+ date.getDate() + "日" + " "
+ date.getHours() + ":"
+ date.getMinutes() + ":"
+ date.getSeconds();
}

需要注意的地方,有两点:
1. 获得年份的时候,使用的是 getFullYear(),而没有使用 getYear();
2. 月份使用 getMonth(),需加 1 才是真是月份值。


为什么没有使用getYear(),而使用的是getFullYear()呢?
因为getYear()同样存在兼容性问题。

getYear()兼容性问题

MSDN 如此描述这个方法的:
对于1900-1999这段时间,调用 getYear() 方法将返回的年份值是一个两位数字的整数,它代表了所保存的年份与 1900 年之间的差距。而对于其它的年份,返回值是一个四位的整数。
参见MSDN:http://msdn.microsoft.com/en-us/library/x0a9sc10%28VS.85%29.aspx
注意上面所说的"其他",是指1900年以前,2000及以后.

其它浏览器此部分的官方文档中则说明:
getYear() 返回的值始终为 Date 对象中的年份与 1900 年之间的差值。
这个个方法已经过时,之所以提供这个方法,是为了保持向后的兼容性。请改用 getFullYear 方法。


通过测试,对比一下这两个方法:
<div id="show"></div>
<script language="JavaScript">
window.onload = function() {
var dateArray = [ "0000", "0001", "0099",
"0100", "0500", "0999",
"1000", "1001", "1500",
"1899", "1900", "1901",
"1999", "2000", "2001",
"2009"];
var i = 0;
for (i = 0; i < dateArray.length; i++) {
var msg = "";
var date = new Date("Jan 01, " + dateArray[i] + " 01:00:00");
msg = dateArray[i] + ": " + "getYear(): " + date.getYear() + "; " + "getFullYear(): " + date.getFullYear();
showMsg(msg);
}
}
function showMsg(msg) {
document.getElementById('show').innerHTML += msg + "</br>";
}
</script>


Firefox 和 Opera:
0000: getYear(): NaN; getFullYear(): NaN
0001: getYear(): NaN; getFullYear(): NaN
0099: getYear(): 99; getFullYear(): 1999
0100: getYear(): -1800; getFullYear(): 100
0500: getYear(): -1400; getFullYear(): 500
0999: getYear(): -901; getFullYear(): 999
1000: getYear(): -900; getFullYear(): 1000
1001: getYear(): -899; getFullYear(): 1001
1500: getYear(): -400; getFullYear(): 1500
1899: getYear(): -1; getFullYear(): 1899
1900: getYear(): 0; getFullYear(): 1900
1901: getYear(): 1; getFullYear(): 1901
1999: getYear(): 99; getFullYear(): 1999
2000: getYear(): 100; getFullYear(): 2000
2001: getYear(): 101; getFullYear(): 2001
2009: getYear(): 109; getFullYear(): 2009


IE:
0000: getYear(): NaN; getFullYear(): NaN
0001: getYear(): NaN; getFullYear(): NaN
0099: getYear(): 99; getFullYear(): 1999
0100: getYear(): 100; getFullYear(): 100
0500: getYear(): 500; getFullYear(): 500
0999: getYear(): 999; getFullYear(): 999
1000: getYear(): 1000; getFullYear(): 1000
1001: getYear(): 1001; getFullYear(): 1001
1500: getYear(): 1500; getFullYear(): 1500
1899: getYear(): 1899; getFullYear(): 1899
1900: getYear(): 0; getFullYear(): 1900
1901: getYear(): 1; getFullYear(): 1901
1999: getYear(): 99; getFullYear(): 1999
2000: getYear(): 2000; getFullYear(): 2000
2001: getYear(): 2001; getFullYear(): 2001
2009: getYear(): 2009; getFullYear(): 2009


Chrome:
0000: getYear(): 100; getFullYear(): 2000
0001: getYear(): 101; getFullYear(): 2001
0099: getYear(): 99; getFullYear(): 1999
0100: getYear(): -1800; getFullYear(): 100
0500: getYear(): -1400; getFullYear(): 500
0999: getYear(): -901; getFullYear(): 999
1000: getYear(): -900; getFullYear(): 1000
1001: getYear(): -899; getFullYear(): 1001
1500: getYear(): -400; getFullYear(): 1500
1899: getYear(): -1; getFullYear(): 1899
1900: getYear(): 0; getFullYear(): 1900
1901: getYear(): 1; getFullYear(): 1901
1999: getYear(): 99; getFullYear(): 1999
2000: getYear(): 100; getFullYear(): 2000
2001: getYear(): 101; getFullYear(): 2001
2009: getYear(): 109; getFullYear(): 2009


Safari:
0000: getYear(): 100; getFullYear(): 2000
0001: getYear(): 101; getFullYear(): 2001
0099: getYear(): 99; getFullYear(): 1999
0100: getYear(): -1801; getFullYear(): 99
0500: getYear(): -1401; getFullYear(): 499
0999: getYear(): -902; getFullYear(): 998
1000: getYear(): -901; getFullYear(): 999
1001: getYear(): -899; getFullYear(): 1001
1500: getYear(): -400; getFullYear(): 1500
1899: getYear(): -1; getFullYear(): 1899
1900: getYear(): 0; getFullYear(): 1900
1901: getYear(): 1; getFullYear(): 1901
1999: getYear(): 99; getFullYear(): 1999
2000: getYear(): 100; getFullYear(): 2000
2001: getYear(): 101; getFullYear(): 2001
2009: getYear(): 109; getFullYear(): 2009


可见,在获取 1000 年后的日期的年份儿时,getFullYear() 方法还是比较保险的,但是,1000年以及以前的就不保险了。Safari对 100~1000年之间的年份儿,直接少了1年。其他浏览器倒还可以。小于100年的就比较扯了,都很扯。

更多兼容性问题,见:【分享】浏览器兼容性问题目录
...全文
2085 1 收藏 58
写回复
58 条回复
切换为时间正序
请发表友善的回复…
发表回复
虾米 2010-09-14
这个项目一般,都按标准来写,还有就是主要支持ie和火狐这两个浏览器 。。
回复
angdawei 2010-09-12
haha
回复
angdawei 2010-09-12
haha
回复
q396730138 2010-08-14
那么想要分 不如 去抢。。

[Quote=引用 91 楼 liupg_csd 的回复:]
好东西!
[/Quote]
回复
tingfjm 2010-08-12
哎,整天用框架了。基础的都给忘了。。。
回复
moon_demon 2010-07-20
回复
yin_yjing 2010-07-13
谢谢楼主分享
回复
xk029 2010-07-13
回复
牛叔 2010-07-12
getFullYear()记住了。。
还好我一直用这个
回复
爱神兽的熊 2010-07-12
太有用了!
回复
WebAdvocate 2010-07-11
[Quote=引用 43 楼 xdbjzhhh 的回复:]

去TM的兼容性。。。。。。

如果过两年又出一个流行的新的浏览器,是不是全世界的网页全换一遍啊。。。。。

CAO

那些定标准的机构吃屎的啊。。。。。。。。
[/Quote]没辙,标准也不可能什么情况都考虑到,也不可能强制浏览器厂商去支持它制定的标准……
浏览器厂商为了不让自己的浏览器死掉,也会极力的去遵循标准,这个放心。
回复
「已注销」 2010-07-11
去TM的兼容性。。。。。。

如果过两年又出一个流行的新的浏览器,是不是全世界的网页全换一遍啊。。。。。

CAO

那些定标准的机构吃屎的啊。。。。。。。。
回复
tiger_ok1 2010-07-11
收藏。。。。。。。。。。
回复
XNightSky 2010-07-11
getYear() 以后不用了。。
getFullYear()记住了。。
回复
crazyxf 2010-07-11
主流测试就可以了,万能的东西是自己受累而且不讨好。
回复
xiuyouxu 2010-07-10
回复
ac12857 2010-07-10
路过,学习下.
回复
ac12857 2010-07-10
支持.刚开始接触学习中.
回复
guguangshuai1987 2010-07-10
了解一下来
回复
zhanggp210 2010-07-10
支持下
回复
发动态
发帖子
跨浏览器开发
创建于2010-06-28

5004

社区成员

解读Web 标准、分析和讨论实际问题、推动网络标准化发展和跨浏览器开发进程,解决各种兼容性问题。
申请成为版主
社区公告
暂无公告