看完本文,您将了解为什么会有时区、时区为什么这么设计,以及时间是如何测量、统一的。
只想了解概念的朋友,直接走传送门:时区、GMT、UT、TAI、UTC、UNIX时间戳、UNIX 2038问题
MySQL中的时区、日期和时间处理,参见《MySQL日期与时间函数(日期/时间格式化、增减、对比、时区等)》
文章目录
时区为什么需要时区世界各地的时间是“不一样”的全世界需要一个统一的时间标准时区的设计时区划分规则第一个世界时:GMT时间的“长度”和“坐标”GMT的时间测量国际原子时UTC诞生格式计算机世界的时间:UNIX TIME定义使用场景几点疑问为什么Unix纪元时间是`1970-01-01T00:00:00`?时间戳存满了怎么办?时区
为什么需要时区
世界各地的时间是“不一样”的
古人的一天,习惯用日升日落来计算,比如太阳最高就是正午(12时):这就是地方时。
这是千百年来形成的一种习惯和文化。
而地球自转的原因,不同地区阳光照射的角度不同,因此地方时是不同的。
地球自转是自西向东的,所以东边比西边先看到太阳。因为上面的地方时特点,同一客观时刻,东边使用的时间也比西边的早。
所以客观上同一时刻,从不同地区人的意识和表达上,时间是不同的。
全世界需要一个统一的时间标准
随着地区、国家的形成、全球化的推进,不同地方时的人之间有更多的交流。但不同的时间表达,给记录、沟通带来了混乱。
所以世界需要一种统一的时间标准。
最简单的方式,选一个某一个地区的地方时作为时间标准。但这样一来,当这个地区处于正午时、假定是12点,在地球其他经度上,人们可能正处于早晨、深夜、傍晚。人们的表达可能会变成,“12点了,要吃早饭了”、“12点了、要吃晚饭了”,这严重违背了人们千百年形成的习惯,完全没办法接受。
所以在兼顾人们习惯的同时,还要有一个可以协调一致的方案,让大家各自表达各自时间的同时,客观上的时间可以对应上。
时区就是为了解决了这个问题而出现。
时区的设计
时区的设计,既要统一世界的时间,也要兼顾各地区习惯、不同地区还要容易换算。
时区划分规则
1884年,在华盛顿的国际经度会议规定:将全球按经线从东到西划分为24个时区,其中东、西各12个时区,每个时区跨越经度15°,0区和12区跨越东西各7.5°)。规定相邻区域的时间相差1小时(这样24个时区刚好是24小时,地球自转一周),这代表着在同一区域内的东端和西端的人看到太阳升起的时间最多相差不过1小时。
当人们跨过一个区域,就将自己的时钟校正1小时(向西减1小时,向东加1小时),跨过几个区域就加或减几小时。这样使用起来就很方便。
但这个方法也有个问题:如果连续跨越24个时区回到原点,那么时间将会多出或少去一天。
为了避免这种“日期错乱”现象,国际上统一规定180°经线为“国际日期变更线”。当你由西向东跨越国际日期变更线时,必须在你的计时系统中减去一天;反之,由东向西跨越国际日期变更线,就必须加上一天
图片来自香港天文台1
百度的时区图片,更详细,但有防盗链不能引用。
上面的标准是指导意义,而各地实际遵照的时区,并不一定严格对照所处经度。因为有很多国家或地区同时跨越多个时区,为了照顾到行政上的方便,常将1个国家或1个省份划在一起时区里。所以时区并不严格按南北直线来划分,而是按自然条件来划分。例如,中国幅员宽广,差不多跨5个时区,但为了使用方便简单,实际上在只用东八时区的标准时即北京时间为准。
第一个世界时:GMT
确定时区规则后,会议还规定英国(格林尼治天文台旧址)为零时区。这就诞生了第一个世界时(Universal Time,缩写为UT):格林尼治标准时间(Greenwich Mean Time,缩写为GMT,又称格林尼治平时)。
GMT 12:00就是指格林尼治天文台当地的中午12:00,而GMT+8 12:00,则是指的东八区的北京当地时间的12:00。
GMT最早只是英国的基准时间。
格林尼治天文台建于1675年,当时,英国航海事业发展迅速,为了解决在海上测定经度的需要,英国当局决定在伦敦东南郊距市中心约20多千米,泰晤士河畔的皇家格林尼治花园中建立天文台。
1835年以后,格林尼治天文台在杰出的天文学家埃里的领导下,得到扩充并更新了设备。他首创利用“子午环”测定格林尼治平太阳时。该台成为当时世界上测时手段较先进的天文台。
19实际上半叶,当时很多国家建立了自己的本初子午线,但随着世界航海事业的发展,各地区同步时间变得很不方便。后来在1884年的的国际精度会议上,决定以通过当时格林尼治天文台埃里中星仪所在的经线,GMT也成为了世界基准时间。
尽管1884年才确立这个时间系统概念,但实际上1924年开始,格林威治天文台每小时就会向全世界播报时间。此后,GTM由英国伦敦的格林威治皇家天文台计算并维护,并在往后的几十年往欧陆其他国家扩散。
时间的“长度”和“坐标”
GMT的时间测量
在刚开始的几十年,GMT 的测量方法非常简单:观测者随时监控太阳在天空的位置,并且把每天太阳爬升到仰角最高的时候记录下来,这个时间点称呼为“过中天”。一般人对于一天 24 小时的理解,大致上就相等于两次太阳过中天的时间间隔。
但由于地球是以椭圆轨道绕着太阳,在轨道上的行进速率不一,导致一年之中会有“比较长的一天”与“比较短的一天”,所以格林威治的观测者必须要至少连续观测一年,然后求取 365 个长度不一的“天”,再把他们全部平均后,得到固定的一天长度,之后再细分成时、分、秒等单位。
因为这些特性,实际上GMT是有秒级误差的。
后来科学家发现了由于地轴摆动、不同地点测量的世界时会有差别,为此制定了新的标准UT1,之前的GMT称之为UT0;再后来科学家发现由于地球自转率的季节性变动,UT1具有周期性变化,修正上述影响后,得到了更均匀的UT2。
国际原子时
在1960年以前,GMT尽管有些许不精确,但仍作为基本时间计量系统被广泛应用。
(中间短暂的被历书时代替)
1967年第十三届国际计量大会(CGPM)决定,把秒的定义改成原子钟导出的原子时秒。
铯 -133 原子基态的两个超精细能级间在零磁场下跃迁辐射9,192,631,770周所持续的时间
自此时间测量就与地球自转脱节了。这个只利用原子钟计算时间与日期的系统,称作国际原子时 (International Atomic Time,简称TAI),这是一种只有“天”的系统,时分秒都以“天”的小数点零头来表示。
国际原子时是一个连续性指标, 由1958年1月1日0時0分0秒起,以日、时、分、秒计算,准确度为每日数纳秒,而UT的准确度为每日数毫秒。在确定原子时起点之后,由于地球自转速度不均匀,UT与原子时之间的时差便逐年积累。
TAI的起点是这样规定的:
取1958年1月1日0时0分0秒世界时(UT)的瞬间作为同年同月同日0时0分0秒TAI。(事后发现,在该瞬间原子时与世界时的时刻之差为0.0039秒。这一差值就作为历史事实而保留下来。
UTC
尽管获得了更精确的时间测量,但许多应用部门要求时间系统接近世界时。
既要以国际原子时为计算基准,但时间又要尽量接近UT、让一般人都方便使用,UTC就是为了这个目标而设计。
诞生
1972年诞生了一个折衷方案:协调世界时(Universal Time Coordinated,缩写为UTC)12。UTC是当前的世界标准时间。
协调世界时,即以我为基准,向我看齐的意思。(英语:Coordinated Universal Time,法语:Temps Universel Coordonné,简称UTC)是最主要的世界时间标准,由于英文(CUT)和法文(TUC)的缩写不同,作为妥协,简称UTC。
中国大陆采用
ISO 8601
的《数据元和交换格式信息交换日期和时间表示法》(GB/T 7408-1994)称之为国际协调时间,代替原来的GB/T 7408-1994;中国台湾采用CNS 7648
的《资料元及交换格式–资讯交换–日期及时间的表示法》,称之为世界统一时间
为了确保UTC与GMT相差不会超过0.9秒,在有需要的情况下会在UTC内加上正或负闰秒。所以,UTC与GMT基本上等同,误差不超过0.9秒。所以在实际上,UTC与GMT近乎相同。
按国际无线电咨询委员会(CCIR)通过的关于UTC的修正案,从1972年1月1日起UTC与UT1(在UT中加入极移改正得到)之间的差值最大可以达到±0.9s。位于巴黎的国际地球自转事务中央局负责决定何时加入闰秒。一般会在每年的6月30日、12月31日的最后一秒进行调整。UTC与TAI之间会出现若干整数秒的差别,但两者频率保持一致。
这样UTC按原子时的频率、保持了时间尺度的均匀性,又能近似地反映地球自转的变化。
由于 UTC直接与国际度量衡标准相联系,所以目前所有的国际通讯系统,像是卫星、航空、GPS 等等,全部都协议采用UTC 时间。
随着UTC的诞生,之前的各种计时方案使用越来越少。尽管如此,GMT等世界时,在日常生活、天文导航、大地测量和宇宙飞行等方面仍属必需;同时,世界时反映地球自转速率的变化,是地球自转参数之一,仍为天文学和地球物理学的基本资料。
格式
国际标准化组织规定了日期和时间的表示方法,ISO 8601规定了日期和时间相关的数据交换时的格式。UTC的标准格式为-11-11T00:00:00.000Z
,由三个部分组成:
T
代表使用UTC时间Z
是UTC偏移量,表示UTC时间与本地时的差别、即时差。Z
本身表示0时区,读作Zulu
。写作Z
或不写的时候,表示不偏移、即GTM/0时区的时间。需要偏移时,将Z替换为真实的偏移量。偏移量可用以下形式表示:±[hh]:[mm]
、±[hh][mm]
、±[hh]
目前有39个UTC偏移量(当伊朗试行夏令时时只有38个)偏移量除了数字,也可以写时区名 时间数值。表示在限定UTC格式和偏移量的情况下,偏移时区的本地时间。
看一个例子:
GMT时间无需偏移,写作-11-11T00:00:00.000
。北京在东8区、比GMT要早8小时,写作-11-11T08:00:00.000+0800
计算机世界的时间:UNIX TIME
定义
Unix时间(Unix Time),也叫做POSIX时间或纪元时间(Epoch Time),是用来记录时间的流逝,所以也常被叫做时间戳34。 定义为从 从定义可以看到,它只代表了从Unix纪元开始流逝的秒数,所以你身处地球上何处,这个时间都是一样的。 一般Unix时间都是精确到秒,但也有些地方Unix时间是精确到毫秒的(比如MySQL 5.6.4之后开始支持到微秒)。 Unix时间主要用于Unix或类Unix系统,但在文件系统、数据库系统、开发语言等方面也有广泛应用,如C/C++、Java、MySQL等。也存在一些其他操作系统或者编程语言,使用的就是不一样的纪元起始日期了,比如MFC使用的是 Unix系统中计算机内部的时间都是使用Unix时间的。而给用户看时,就需要转换成日期和时间的这种对人友好的形式。 在类Unix系统上,可通过命令 这个问题得去问Unix之父:Ken Thompson 和 Dennis Ritchie了,是他们选择这个时间作为Unix系统的纪元时间的4。 第一版的Unix程序员手册是1971年11月份出版的,上面定义Unix时间是“从 有一种说法是Unix操作系统诞生于1970年,但实际上并不是的,在1969年左右,Unix的概念就已经诞生了,Unix的最早版本已经诞生了。Wired网站上的一篇文章写道 Ritchie说这个时间其实是随意选择的,因为需要一个统一的日期来作为时间的起点,而1970年的元旦,看起来是最方便的。 目前已知操作系统、文件系统、数据库系统、开发语言等,都可能因使用或借鉴了Unix,存在类似问题。 在32位系统中一般时间戳占用4字节,还有一些系统如MySQL也如此。 32位、去除符号位,剩余位数最多表示 对于操作系统而言,目前我们大部分的系统都已经升级到64位系统,理论上可以一直表达到 是否会发生2038年问题,并不绝对取决于是32位系统还是64位系统。而是由具体系统中对 除了操作系统,开发语言或数据库系统,有些不一定依赖于系统的 要想知道你的电脑不幸到2038年还没坏,会不会遇上末日,可以用下面的方法尝试: 在GNU/Linux上执行 在BSD上执行 如果系统使用了64位时间,结果应该是 以上。感谢您的阅读。 本文未尽事项,后续有机会补充 时区名ISO8601的详细解读UNIX时间戳的限制,广泛存在于多种计算机系统中,具体的区别、改造情况有哪些 香港天文台 - 世界时区图:http://gb.weather.gov.hk/gts/time/clock/clockHc.htm# ↩︎ ↩︎ 百度 - UTC:/item/%E5%8D%8F%E8%B0%83%E4%B8%96%E7%95%8C%E6%97%B6/787659?fr=aladdin ↩︎ UNIX时间戳 - 百度百科 :/item/unix%E6%97%B6%E9%97%B4%E6%88%B3/2078227?fr=aladdin ↩︎ UNIX时间 - 维基百科:/wiki/Unix_time ↩︎ ↩︎ UNIX时间2038问题:/wiki/Year_2038_problem ↩︎1970-01-01T00:00:00
开始流逝的秒数,不考虑闰秒。之后的时间是正数,之前的是负数。使用场景
1899-12-30T00:00:00
。date +%s
查看当前Unix时间:几点疑问
为什么Unix纪元时间是
1970-01-01T00:00:00
?1971-01-01T00:00:00
开始,单位是一秒的六十分之一”。这意味在Unix时间的最早版本中,时间计数器以60Hz的频率(芯片的振荡器频率)递增,每隔1/60秒,计数器就加一。当时使用的整数计数器是32位的,这样Unix时间能够表示的范围就非常受限了,232/60/3600/24/30/12≈2.3年。所以后来经过多次更改,频率变成了1Hz,纪元时间改为了1970-01-01T00:00:00
。时间戳存满了怎么办?
2^31-1=2147483647秒≈24855天≈68年
,有人计算过是2038-01-19T03:14:07。到了那个时刻,时间戳字段存满就会溢出;如果在那个时候,目前大多数系统或语言还没有修改时间戳的长度,计算机世界的世界末日就来了!515:30:08 UTC on Sun, 4 December 292,277,026,596
,也就是几千亿年后。可惜太阳系几十亿年后就要毁灭了,人类不一定能见到那个时刻;要是人类幸存下来了,应该有的是办法解决这个问题了。time_t
类型的实现决定。NetBSD
和OpenBSD
的早期版本在amd64
平台上仍然使用了32位time_t
,因此仍然会发生2038年问题。如今也有一些32位系统开始使用64位的time_t
类型。64位Linux
上已经在使用64位的time_t
了,而32位Linux
上则似乎仍然是32位
。Mac OS也已经不用担心2038问题,亲测1万年以上没问题。time_t
,是否已解决了2038问题,要看其支持情况。目前Java
是没有该问题的,MySQL 8.0
的timstamp
还有该问题。date -ud @2147483648
date -u -r 2147483648
:Tue Jan 19 03:14:08 UTC 2038
,即超出32位时间戳最大值1秒。这样就可以度过末日了。UNIX
这块,本人对计算机历史、系统原理了解有限,大量参考了/entry/95734这篇文章。原文还有很多扩展,感兴趣的朋友可以去读一下。MySQL中的时间取值范围和存储原理,可参考《MySQL字段长度、取值范围、存储开销(5.6/5.7/8.x的主要类型,区分显示宽度/有无符号/定点浮点)》MySQL中的时区、日期和时间处理,可参考《MySQL日期与时间函数(日期/时间格式化、增减、对比、时区等)》一个看时间的网站:https://time.is/