我要投搞

标签云

收藏小站

爱尚经典语录、名言、句子、散文、日志、唯美图片

当前位置:2019全年资料大全正版 > 泛型类型 >

【第719期】关于Javascript中Date类型的常见问题与建议做法

归档日期:06-24       文本归类:泛型类型      文章编辑:爱尚语录

  原标题:【第719期】关于Javascript中Date类型的常见问题与建议做法

  hi,大家国庆节快乐,早读君如期来了。今天要分享的这篇文章是第17号台风来的那晚在宿舍里翻译的。在台灯下敲着文字,那种感觉非常宁静,早读君很喜欢这种的状态。今天这篇文章得到作者@Will保哥的授权,谢谢~

  今天这篇文章,我想来谈谈Java到底是如何实现[日期字符串]格式解析,日期时间有太多种的表达方式,一般人在刚接触日期格式的时候,都不会想太多跨浏览器的问题,通常都是遇到问题的时候才来埋怨浏览器有多烂多烂。有趣的是,有时候还会错怪对象,例如xxx框架好烂,我写JS这么久都没遇到过这种问题,用了xxx框架才遇到的。现在,我们就开头开始来说对这个说常用不常用,用到时不熟悉的[日期]类型。

  我这几年遇到Java的许多灵异事件,除了Number意外,就属Date最诡异了,美国一段时间就会爆出惊人的意外之喜。

  你在任何浏览器开发者工具的Console模式下,只要输出Date对象的结果,一律都会使用[本地时间]来显示该对象的日期时间

  第三种 new Date(dateString) 是我们这篇文章讨论的重点,也是最雷的用法。

  一般来说,我们比较少会直接用 new Date(dateString)语法来创建日期对象,如果会直接用,通常都是先从Ajax或其他地方读取一个[日期格式的字符串]值,然后才透过new Date(dateString)解析字符串为Date类型的对象。不过,大部分时间都是读取数据后直接输出字符串的,因此大家不用会遇到解析日期的问题。

  但如果牵扯到日期的相关计算,例如想要计算两个日期之间的天数,或是想知道从特定时间点算起60天后是几月几号,或是想显示自定义的日期格式,都很有可能会用到日期字符串格式来解析。

  是的,没错,我们传入的第二个参数为月份,但是你传入的是9,却返回的是10月,因为只有这个月份的参数是从0开始计算的,没人知道为什么。

  你知道如果传入12代表哪个月份吗?很神奇的是13月,也就是今年年份的12月自动加上1一个月,如果你执行的是new Date(2016,12,1);的话,你得到的日期对象将会是2017-01-01这个日期,你说雷不?

  现在就要进入Date类型最雷的用法了,就是看他如何解析字符串,还有更重要的就是你通用想传入怎么日期格式的字符串?

  先别说java Date有多雷,浏览器本身就雷的话,其他就不用说了,请尊重生命,没事不要用ie8上网。

  这几个较新IE版本真的稍微会比较正常点,我觉得2016-09-24这种格式不接受还算优点道理,各位鞋web api的时候要注意了,不要随便产生这种格式的日期字符串。

  看到下图的执行结果,嘴角总是微微上扬,不枉费我们这么爱用google chrome浏览器。

  请看一下下图第一个案例(2016-09-24)与第三个案例(2016/09/24),如果你仔细会发现,返回显示的日期时间,两者相差了8个小时。

  这时因为第一个案例被chrome解析为GMT格林威治标准时间的日期,我们的[本地时间]是GMT+8,因此显示时间会自动加上8个小时来显示。

  我们再来看看第三个案例,它显示的就是[本地时间]的2016/09/24,这个小差别你必须特别注意,因为你打开网页的人不见的都位于台湾时区,因此显示的七日有可能不是2016/09/24,如果你的电脑时区设置在其他地区,也有可能会显示2016/09/23.

  人们都说Safari就是另一个IE浏览器不是没有道理的,连特征都跟IE~11很像,可惜现在大部分ios9跑的也是safari9的版本

  接着我们再加上[时间]部分的字符串,看看各浏览器之间如何解析[日期时间]字符串格式的执行结果。

  差别又出现了,什么?2016-09-24 12:21:00 这种格式你也不接受,你在开玩笑吗?

  我们加上时间之后,原来第一种案例与第三种案例,不再会相差8个小时了,而是通通解释为本地时间

  即便到了safari10最新版本,第一种格式不支持就是不支持,脾气很硬啊。

  如果深在台湾,一般人都不习惯用欧美习惯的日期表示法(9 September, 2016 12:21:00)来创建日期时间字符床,因为从上述测试的情况来看,这种格式反而是最没问题的。不过,也不是真的那么[没问题],请各位想想,如果上网的人不在台湾,而你的日期时间代表的是[台湾时区]的时间,这时透过java解析出来的时间,就是错误的。因为浏览器预设会将这个日期格式的字符串解析为[用户目前浏览器的本地时间],如果你又刚好降日期显示出来,那么时间就很有可能出现误差,除非你在页面上很明确地说这个时间就是台湾时区的时间。

  我最常看到的日期格式应该是2016-09-24 12:@1:22这种,但你可以发现,从上述测试的案例来看,在IE6~8以及它的兄弟safari并不支持这种用法,这包含iPhone/iPad内置的safari版本,因此移动版网页遇到这种日期格式,通通完蛋。

  事实上,这种标准的日期格式,也可以允许只有日期部分,而且还不一定要写完整的日期格式,只有年份也可以当成合法有效的日期格式。

  至于时间部分,日期的部分也不能省略,而日期与时间部分回固定用一个T来分隔。时间的部分,从[秒]开始也是可以省略,不一定要完整的时间格式,而且时间格式最后的Z代表的是Time zone的意思,这个字段也是可以省略的。

  如果把日期与时间组合在一起,就有非常多钟可能的变化,以下我举的几个例子,这些都是合法有效的日期格式字符串:

  “java 啊 java,枉费我跟你相处这么久,为什么你总是让人搞不懂啊”这句话不知道在多少web开发人员心中出现过,我的[前端工程研究]系列就是试图解决大家长久以来最搞不懂的坑。

  请记得一件事,解析日期时间字符串格式时,在ES3规范中根本没有定义应该的日期时间字符串格式,到了ES5才有了明确的ISO-8601格式规范。

  在那个没有明确定义日期时间字符串格式的ES3年代(IE6~8),当时各浏览器都职能各自实现自己的日期时间格式解析代码,因此跨浏览器之间的兼容问题自然会有。但当初毕竟浏览器都是美国人做的,所以用美国时间常见的日期时间格式来解析,肯定是没有问题的。比如:Sat, 24 Sep 2016 20:42:16 、 Sat, 24 Sep 2016 20:42:16 GMT 或 Sat, 24 Sep 2016 20:42:16 GMT+0800 等等。

  而到了ES5规范问世之后(IE9+),因为必须向前兼容早起的实现,所以只要不是ISO-8601的日期格式出现,不同浏览器之间,还是会有可能出现不同的解析结果,像是safari对于2016-09-24 20:42:16这种格式就一直不支持的,你也不能说他错,他们就是遵照ES5规范去实现而已,所以大家也不用抱怨了,多一点包容与理解,世界才有可能更加祥和。

  如果你的网站还是必须支持ie8或以下浏览器的线以下的java runtime并没有实现es5规范,所以当你的web api响应iso-8601日期格式,旧版ie浏览器还是无法解析,这个问题还是必须要考虑进去。

  如果你要我给建议的话,我可以说兼容性最高的应该就是Sat, 24 Sep 2016 20:42:16 GMT这种日期时间格式,但请注意这种格式的缺点是[如果你没有加上GMT时区,浏览器预设酒会变这种格式解析为用户电脑的本地时间],如果没注意到时区部分,对于全球性或跨国浏览用户来说可能会出现错误的时间差,否则请一律使用ISO-8601标准日期时间格式( 2016-09T02:34:33.346Z ),这种格式的优点就是[浏览器只会将这种格式解析为GMT/UTC标准时区的时间],这样反而可以强迫你用具有时区的思维来开发代码,出现时差错误的问题也会减少。

  下次大家在抱怨浏览器或框架之前,建议先查过java的权威文件,我心目中的java权威文件是java mdn网站,上面对java的介绍与说明一致都是最精华也是最完整的,大家可以多多利用。

  以下补充在写c#的DateTime格式时,方便转换成ISO-8601日期时间格式代码范例:

本文链接:http://buggystordera.com/fanxingleixing/681.html