js - - - - - js获取new Date()时区时差问题

js获取new Date()时区时差问题

  • 1. 概念描述
    • 格林威治时间
    • 时区
  • 2. 业务场景描述
  • 3. 解决办法

1. 概念描述

格林威治时间

格林威治子午线上的地方时,或零时区(中时区)的区时叫做格林威治时间,也叫世界时。

比如我们中国是东八区,北京时间是(GMT+08:00)

时区

时区是地球上的区域使用同一个时间定义。以前,人们通过观察太阳的位置(时角)决定时间,这就使得不同经度的地方的时间有所不同(地方时)。1863年,首次使用时区的概念。时区通过设立一个区域的标准时间部分地解决了这个问题。

地球是自西向东自转,东边比西边先看到太阳,东边的时间也比西边的早。地球自转一周是24小时,所以划分为24个时区,即东1—12区,西1—12区,相邻两个时区的时间相差1小时

2. 业务场景描述

需要实现一个倒计时抽奖功能,当北京时间为 2024/1/1 00:00:00 的时候,页面“抽奖”按钮可点击。

代码示例如下:

let target = Date.parse('2024/1/1 00:00:00'); // 获取目标时间时间戳
let now = Date.now(); // 获取当前时间时间戳
if( now >= target ) {
// 当前时间大于等于目标时间(即目标时间已经过去)console.log('开始抽奖')
} else {console.log('抽奖时间未到')
}

上述代码简单的使用两个时间戳进行比对。如果不考虑时区问题,是正确的。

但如果考虑时区问题,当北京时间已经达到了2024/1/1 00:00:00,由于不同时区存在着时差,其他时区可能还没到该时间。北京所在时区的已经开始抽奖了,其他时区还在等待时间倒计时。

那么该如何矫正以达到绝对的公平性、同时性呢

3. 解决办法

方案一:利用时区时差,把本地时间转换为目标时区目标时间时间,然后进行对比
方案二:统一使用服务器时间


已知格林威治时间,换算本地正确时间

本地时间 = 格林威治时间 - 时差

已知本地时间,换算对应格林威治时间:

格林威治时间 = 本地时间 + 时差

已知本地时间,换算其他时区的时间
因为时区间的差异是以小时为单位的。所以算出0时区的时间后,再减去或加上相应的小时即可(东N区便+N小时,西N区便-N小时)。 为了方便计算,东N区记做正数,西N区记做负数,即:

目标时区时间 = 本地时间 + 时差 + 时区间隔


把本地时间转换为目标时区目标时间时间,然后进行时间比对(如:将本地时间转换为东8区时间)

	 function convertToTargetTime(timeZone) {//目标时区(**东时区记做正数,西时区记做负数**)let zoneOffset = timeZone || 8;// 本地时间和格林威治的时间差,单位为分钟。     (* 60 * 1000 单位转换为毫秒)let offset_GMT = new Date().getTimezoneOffset() * 60 * 1000;// 算出本地当前时间: (单位为毫秒)let localDate = new Date().getTime();// 计算时区间隔: (单位为毫秒)let timeZoneInterval = zoneOffset * 60 * 60 * 1000;// 转换到目标时区后的时间: (单位是毫秒)let timeAfterConversion = localDate + offset_GMT + timeZoneInterval;console.log("东8区现在是:" + timeAfterConversion);return timeAfterConversion;}// 获取目标时间时间戳let target = Date.parse('2024/1/1 00:00:00'); // 获取转换为东8区的时间戳let timeAfterConversion = convertToTargetTime(8)//  时间对比if( timeAfterConversion >= target ) {// 当前时间大于等于目标时间(即目标时间已经过去,可以开始抽奖)console.log('开始抽奖')} else {console.log('抽奖时间未到')}

如此即可保证时间的同时性!