JavaScript Date类型与时区同步

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26025363/article/details/79486756

JavaScript Date类型

场景问题:

  1. 场景
    在做SPA单页面应用时,有个时间展示的问题。应用的很多方面都是基于时间来做的,比如报表、记录、日志等很多跟时间有关的内容。
    如果想要实现windows的系统中修改时间的功能,包括时区的话。
    主要的需求是这样的,首先是应用页面的右上角展示时间,是动态的改变的。其次,有一个修改系统时间的模块,该模块可以修改时间、并且修改系统的时区。跟windows的一样。

  2. 问题:

方案1

首先,考虑前段不做处理,所有的时间信息都是后台给,后台给字符串,然后根据字符串直接展示在前台。修改系统时间,就把时间发送给后台,后台处理完,在生成一个字符串传给前台。
这样做会有很多问题:首先是性能消耗太大,每秒时间变动都要向后台请求数据,可能由于网络延迟等问题,展示的时候也不是一秒一秒的跳。并且没有动态的一些改变时区的问题。相信也没有人会这么做。

方案2

后台给前端传Date类型数据,但是这样的话,不同的后台生成的Date型数据可能不同,接口不好调。
在此基础上,可以传毫秒数。
毫秒数是一个long型数字,不同的后台实现起来也很容易。
JavaScript的Date()方法原生支持new Date(毫秒数)来展示一个时间。而且,动态增加的话,直接

setTimeout(function(){
    millsecond+=1000;
    //设置文本
},1000),

这样,就能动态刷新,前台没有很多计算,也不会阻塞setTimeout()一秒的准确度,是有一定的保证的。

展示也没有问题,修改时区的信息,也可以给后台发请求,根据后台传的时区偏移,动态更新修改时间的界面。

那么问题来了:如果客户更改了电脑的系统时区,会有什么情况呢?
做个试验:
电脑系统时区是:(UTC-08:00)太平洋时间(美国和加拿大)
电脑系统时间是:2018‎年‎3‎月‎8‎日 0:21:17
打开浏览器console,输入 new Date() 输出是Thu Mar 08 2018 00:21:17 GMT-0800 (太平洋标准时间)

换个时区:(UTC+08:00)北京,重庆,香港特别行政区,乌鲁木齐
系统时间不变,打开浏览器console,输入new Date(),输出是Thu Mar 08 2018 00:21:17 GMT+0800 (China Standard Time)
可以看到,修改时区对new Date()方法并没有影响。但是一般电脑系统时区的改变,是跟着时间自动变化的。这时候new Date()出来的数据,就会变成Wed Mar 07 2018 16:21:17 GMT+0800 (China Standard Time)时区差16个小时,所以时间也是差16个小时。

new Date()方法给出的时间是与客户机的系统时间有关的,而我们的目的是网页上显示的时间,是与服务器同步的。如果跟客户机同步的话,假设一个人在美国,一个人在中国,同时登陆一个网页应用,在网页上做操作,向服务器提交操作的一些结果,并且结果是带时间信息的,那么,以哪个为准呢?记录怎么保持一致性呢?如果跟服务器同步的话,就不会有这种问题了,每个人不管在什么地方,看到的时间总是服务器的时间。

所以,为了消除这个影响,可以让服务器传0时区距离1970年1月1日起的毫秒数。然后客户端先获取本地系统的时区信息,也将其调整到0时区,然后在用new Date(服务器传过的0时区的毫秒数)来展示。这样,相当于消除了new Date()方法根据客户端本地系统的时间来构造时间字符串的问题。这样,展示的数据是服务器的数据,跟客户端是无关的。不随客户端时区改变。

Date的一些方法

构造函数:

new Date();
new Date(value);
new Date(dateString);

当传入value的构造函数,代表自1970年1月1日00:00:00 (世界标准时间) 起经过的毫秒数。
如果没有输入任何参数,则Date的构造器会依据系统设置的当前时间来创建一个Date对象。
JavaScript的Date对象为跨平台提供了统一的行为。时间属性可以在不同的系统中表示相同的时刻,而如果使用了本地时间对象,则反映当地的时间。
JavaScript 的Date对象提供了数个UTC时间的方法,也相应提供了当地时间的方法。UTC,也就是我们所说的格林威治时间,指的是time中的世界时间标准。而当地时间则是指执行JavaScript的客户端电脑所设置的时间。
获取当前时区偏移是通过
Date.prototype.getTimezoneOffset()返回当前时区的时区偏移。

最终思路

思路就是通过new Date().getTimezoneOffset()获取当前时区相对于0时区的偏移,然后将毫秒数转换为0时区的毫秒数。通过+偏移*1000*60来获取0时区的毫秒数。然后在new Date(0时区的毫秒数),这样展示的就是服务器的毫秒数。

但是,经测试发现出现了一个问题,时区是有夏令时和冬令时的,在某个具体日期,可能就变成夏令时了,这时候会相差一个小时。
但是使用new Date().getTimezoneOffset()这个方法是能获取到当前电脑时间是否是夏令时的偏移量的,但是new Date(转换后的时间)确没有考虑夏令时的问题。
原有在于new Date(value)当传入value毫秒数的时候,是会根据value进行判断的,导致还是跟new Date()方法有个夏令时的一个小时的误差。所以当获取系统的时区的时候,使用new Date(服务器传的0时区的偏移量).getTimezoneOffset(),然后调用new Date(计算过的客户单事件毫秒数),这两个步骤的时区偏移量是一致的。不会有差别。

附图

主要实现的功能类似于windows的时区修改,如下:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_26025363/article/details/79486756