日期类型在浏览器与协议中的差异
概述
我在本文前半部分主要是Javascript的日期类型的兼容性问题,后半部分主要是分析日期类型表现格式在不同协议中的差异。
JavaScript的日期类型的兼容性
最近在做一个项目中,使用了JavaScript来处理时间问题。用到的功能有两个:字符串与日期类型的相互转换,求两个日期的时间差。这么简单的功能,居然也因为浏览器对JavaScript实现的巨大差异,导致了兼容性问题。
日期类型转为字符串
JavaScript中Date类型转为字符串很简单,调用toString()方法就好了,但是结果有差异。
用简单的语句来测试下:
var date = new Date();
console.log(date.toString());
浏览器 | 日期格式 | 协议 |
IE | Thu Feb 8 16:31:08 UTC+0800 2018 | RFC-850 / 1036 |
Fire Fox | Thu Feb 08 2018 16:59:41 GMT+0800 | RFC-822 / 1123 |
Chrome | Thu Feb 08 2018 17:00:38 GMT+0800 (China Standard Time) | RFC-822 / 1123 |
Safari | Thu Feb 08 2018 17:00:38 GMT+0800 (CST) | RFC-822 / 1123 |
由这个表可以看出,日期类型转换为字符串的格式除了IE使用 RFC-850 格式以外,都是 RFC-1123 格式。无论 RFC-850 格式,还是 RFC-1123 格式都是HTTP协议(RFC-2616)允许的日期格式。(具体协议内容,参见协议日期格式)
在时区部分出现 GMT
与 UTC
可以认为都代表的是标准时间(Universal Time),但是它们还是有差异的,其中细微的差别,参见ISO-19018 Terms, abbreviations, graphical symbols and concepts on navigation。
字符串转换为日期类型
其实从上一节已经可以看出,浏览器自身是遵守了标准协议的日期格式,虽然稍有差异可都还处于可接受范围以内。但是当涉及到反向操作,即字符串转换为日期类型时,事情就没有这么简单。
标准协议允许的日期格式,在我看来并不怎么在日常生活中使用,完全是一种基于技术性的考虑定义的一种挺别扭的格式(至少我这么认为的)。另外除了IETF协议定义了日期格式以外,ISO也有关于日期格式的标准(ISO-8601 Representation of dates and times),再加上许多日常使用的格式,如何解析字符串是一个问题。
在高级语言中,解析日期字符串都是有专门的方法,也可以自己定义日期字符串的构成规则,这样很好的解决了解析中最头痛的格式问题。但是JavaScript的parse方法并没有提供自定义日期格式的功能,这一点点的缺陷就是浏览器日期解析兼容性问题的源头。
我编写了一段脚本,用来测试浏览器对此功能的兼容性,结果如下:
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript">
function parse_str_to_date(dateString){
return Date.parse(dateString);
}
</script>
</head>
<body>
<script type="text/javascript">
var dateStrings = [
"Thu Feb 08 2018 16:59:41 GMT+0800", // RFC-822 (1123)
"Thu Feb 8 16:31:08 UTC+0800 2018", // RFC-850 (1036)
"Thu 8-Feb-2018 16:31:08 UTC+0800 ", // RFC-850 (1036)
"2018-02-08T16:31:08+08:00", // ISO-8601
"2018-02-08 16:31:08+08:00",
"2018-02-08 16:31:08 +08:00",
"2018/02/08 16:31:08+08:00",
"2018/02/08 16:31:08 +08:00",
"2018-02-08 16:31:08",
"18-02-08 16:31:08",
"2018/02/08 16:31:08",
"02/08/2018 16:31:08",
"02/08/18 16:31:08"
];
for (var i = 0; i < dateStrings.length; i++){
var s = dateStrings[i];
var dt = parse_str_to_date(s);
var element = "";
if (dt) element = "<p>" + s + " --> " + dt.toString() + "</p>";
else element = "<p style='color:red'>" + s + " --> " + dt.toString() + "</p>";
document.write(element);
}
</script>
</body>
</html>
执行结果如下: