mongodb的时间和时区

在使用Mongo Shell后发现其中展示的时间比中国时间落后8小时而产生的。比如:插入时间是2022年9月7日09:08:15,在Shell中看到的则是ISODate("2022-09-07T01:08:17.430Z"),很多人由此产生疑惑,8小时去哪了?是不是出错了?

理解这个问题首先要理解时区的概念。当你同时向一个身处中国的人和身处美国的人提问现在是几点时,中国人回答中午12点,美国人回答的却是凌晨4点。这有区别吗?他们说错了吗?他们都没错。他们回答不一样是因为身处不同的时区,但是他们指代的都是同一个时间:现在。

也可以说,全世界只有一个时间,只是大家描述它的方式不一样——根据自己身处的地区。而有个现状会把这个问题搞得更复杂,那就是夏令时。

我国现在已经不实施夏令时了(对,过去有过!暴露年龄!),但是世界上有很多国家仍然保留夏令时的习惯。这让原本复杂的时间表达更加雪上加霜。这在实施同样的时间规则的人之间不会造成问题。

但是在国际化的今天,你知道一个中国人跟一个实施了夏令时的德国人约一个会议时间有多难?或者在看到一个德国时间2020年5月7日18点,你知道它是英国时间的几点吗?你不光要知道英德的时差,还要知道2020年5月7日这个时间在德国是不是在夏令时的影响范围内,以及在英国它是不是在夏令时的影响范围内。现在有没有觉得小瞧了时间的复杂性?

为了简化这些复杂的问题,有了UTC (Universal Time Coordinated)时间标准以及表达时间的标准ISO 8601,也就是我们在MongoDB中看到的ISODate。

ISODate的表示方法简单来说就是年月日时分秒+时区。以我们前面的例子来说,身处中国时我们的时区是UTC+8,用ISODate表达则是ISODate("2021-01-01T00:00:00+0800")。这个时间在MongoDB中的表达是ISODate("2020-12-31T16:00:00Z"),其中的Z表示UTC(或者UTC+0)。由于时区的不同导致了表达方式不同,但这两个时间指代的是同一时刻,所以两者没有什么不一样。而在展示时,则应该根据你的用户所处的时区来决定到底显示哪一个结果。

需要注意的是:有些语言的驱动(例如Java/C#)在读取到时间时会自动转换为服务器时间,所以不需要再人为转换。有些语言(例如Python)则不会自动转换。使用时应该根据你的实际情况决定处理方式。

1.GMT时间、UTC时间、CST时间

GMT  格林威治标准时间
UTC 协调世界时
CST 中央标准时间
(1).UTC时间[世界标准时间] 与 GMT时间[格林威治时间]

我们可以认为格林威治时间就是世界协调时间(GMT=UTC),格林威治时间和UTC时间均用秒数来计算的。

世界标准时间 (UTC, Coordinated Universal Time) 是当今民用时间的基础。它使用一天 24 小时时间制,并结合了地球的自转时间与原子钟的高精度度量。

UTC是一个标准,而不是一个时区。UTC 是一个全球通用的时间标准。全球各地都同意将各自的时间进行同步协调 (coordinated),这也是 UTC 名字的来源:Universal Coordinated Time。

(2).UTC时间 与 本地时

UTC + 时区差 = 本地时间

那么东八区时差记为+0800,那么 北京时间 = UTC + 0800

(3).CST 中央标准时间

CST可视为美国、澳大利亚、古巴或中国的标准时间,CST可以为如下4个不同的时区的缩写:

中国标准时间:China Standard Time UT+8:00
美国中部时间:Central Standard Time (USA) UT-6:00
澳大利亚中部时间:Central Standard Time (Australia) UT+9:30
古巴标准时间:Cuba Standard Time UT-4:00