本文梳理JavaScript中UTC与GMT的概念差异,详解getTimezoneOffset()获取时差的原理,并对比Date构造函数、时间戳获取方法及Date.UTC()在时区转换中的具体表现,帮助开发者准确处理本地时间与格林威治时间的换算。
GMT与UTC的基本概念
- GMT即格林尼治标准时间(Greenwich Mean Time)。
- UTC即协调世界时(Coordinated Universal Time)。
尽管GMT与UTC在严格科学定义上并不完全等同,但在常规应用中二者均指代0时区的时间,通常可以互换使用。
对于JavaScript开发者而言,GMT这一标识符应当十分熟悉。
当我们执行new Date()时,返回的字符串如“Wed Jan 06 2021 17:48:30 GMT+0800 (中国标准时间)”中,末尾的GMT即代表该时间所属的时区标识。
以GMT+0800为例,中国位于东八区,因此表示为格林尼治时间加上8小时(遵循东正西负原则,+0800即代表+08:00的偏移量,具体原理可自行查阅相关资料)。
时差的定义与计算
本文所讨论的“时差”特指JavaScript环境下的时间偏移概念,而非地理学意义上的时区差异。
在JavaScript中,时差定义为格林威治时间(GMT/UTC)与本地时间之间的差值。
其核心逻辑如下:
格林威治时间减去本地时间等于时差。
通过上述关系进行简单换算,可以得出以下结论:
- UTC + 8 = GMT + 8 = 北京时间(中国属于东八区)。
- 格林威治时间加上8小时即为北京时间。
- 格林威治时间减去北京时间的结果为-8。
- 通用公式为:格林威治时间 - 本地时间 = 时差。
获取时差的方法:getTimezoneOffset()
JavaScript内置了一个专门用于获取时差的方法。
getTimezoneOffset()方法返回格林威治时间(UTC)与本地时间之间的时差,单位是分钟。
具体调用方式如下:
new Date().getTimezoneOffset() // -480JavaScript时间戳与时区关系
时间戳是指指定日期和时间距离1970年1月1日午夜(GMT时间)之间的毫秒数。
在理解时间戳时,有两个关键点必须同时满足:
- 基准时间为1970年1月1日0时0分0秒。
- 该基准时间指的是格林威治时间(GMT/UTC)。
设置日期与时间的方式
new Date()构造函数可以不传入参数,也可以接受多种不同类型的参数。
当传入时间戳(毫秒数)时:
- 系统首先根据传入的毫秒数计算出对应的GMT时间,随后将其转换为本地时区时间。
- 因此,传入0作为参数时,得到的并非本地时间的0点,而是本地时区对应的时间(例如在中国东八区,得到的是8点)。
当传入时间字符串时:
- 字符串格式可以是“1970-1-10 0:0:0”这样的形式。
- 也可以在字符串末尾补充指定时区,例如“1970-1-10 0:0:0 gmt+0900”。
- 不指定时区, 默认是 GMT+0800(中国是东8区)
- 最终,系统会将解析后的时间转换为本地时区。
当使用new Date(year, month, day, hours, minutes, seconds, milliseconds)构造函数时:
- 至少需要传入两个参数(年和月),若后续参数传null或不传,则默认为当前时间的值。
- 传入的参数被视为本地时区时间。
- 最终生成的Date对象也代表本地时区时间。
获取时间戳的多种方法
JavaScript提供了多种获取时间戳的方法:
- new Date().getTime()
- new Date().valueOf()
- +new Date()
- Date.now()
上述方法返回的时间戳,是将本地时间(如北京时间)换算为GMT时间后,再计算其与1970年1月1日0时0分0秒之间的毫秒差值。
Date.UTC()方法的使用
语法为Date.UTC(年, 月, 日, 时, 分, 秒, 毫秒)。
该方法返回的时间戳直接基于GMT时间,计算其与1970年1月1日0时0分0秒的毫秒差值。
UTC()方法可根据世界时(UTC)返回从1970年1月1日到指定日期的毫秒数。
参数不能为空,但如果缺失某些参数,系统会以0进行补充。
UTC、时差与本地时间关系的代码表达
var _date = new Date();
var _UTC = Date.UTC(_date.getFullYear(), _date.getMonth(), _date.getDate(), _date.getHours(), _date.getMinutes(), _date.getSeconds(), _date.getMilliseconds());
var _BJ = _date * 1;
var _timeDifference = new Date().getTimezoneOffset() * 60 * 1000
_BJ - _UTC === _timeDifference // true
//end
总结
以上为个人经验总结,希望能给大家一个参考,也希望大家多多支持本站。