`

关于时区、时间、时刻

 
阅读更多

关于时区,其实应该是个地理概念。通常情况下,当我们跟别人说:“现在是上午11点23分”这句话时,隐含了一个信息,那就是我们做了一个假设:我们都处在同一个时区——标准时间东八区,或者是电视上常说的“北京时间”。这也说明了一件我们平时可能并没太注意的一件事情,时间是和时区紧密挂钩的一个概念。

但时刻就不同了,他是一个和时区没有任何联系的概念,中国有句古话叫“此时此刻”,可以当做现在时刻的一个等价表达。换个更容易理解的方式说就是:此时此刻,可以表示是北京时间的上午11点23分,同时也是美国西雅图的晚上8点23分(按照西雅图的夏令时计算,两边时差相差15个小时)。

但是在这个缩写泛滥的时代,当你发现你需要和服务器上各种local time打交道的时候(尤其是server本身采用了不同时区的时间标准的时候),你会发现,这个时间其实并没有那么简单。CST/UTC/PST/PDT/DST这些恼人的缩写可能不仅仅搞的你晕头转向,更糟糕的是,可能会让某些你需要时间相关任务并没有按照你预期的时刻运行,而是跑到了另一个时刻了!

要想完全搞清楚上面那一串缩写,还是得回头看看时区的概念。注意,以下讨论仅仅针对时区划分模型,暂时忽略真实地理位置行政因素造成的时间在时区内的定义。(比如中国地理位置东西横跨几个地理时区,不过还是统一使用北京时间)

关于时区

理论上的定义,可以在wiki上查到,这里不再赘述。其实我们很容易理解将地球的经线做个24等分,每个等分段作为一个时区,因为人类规定了,一天24小时嘛。

但是问题也来了,每个时区时间由谁来定义?

一种简单粗暴的做法是:每个时区里面的人自己定义时间点来维护自己时区的时间(其实欧美很多地区的夏令时机制,说白了就是这么回事,人为将原本当地的时间调快了一小时)。但是,就像北京奥运会的口号一样,One World嘛,总得有个大家统一认可的标准来界定时间,至少是个指导时间。于是,全世界需要一个时间定义基准坐标点。本初子午线作为分隔东西经线的起点,作为这个基准点也就无可厚非了。于是GMT闪亮登场了。GMT是Greenwish Mean Time的缩写,也是普通人最熟悉的格林尼治标准时间的英文定义。正午十二点被定义为太阳在格林尼治上空最高点时的时刻。这样,这个东西经起点的时区的时间就定义好了,剩下的其他时区的只要简单依次递增或递减一个小时就出现了一套时间系统。

对应到计算机领域,绝大部分的数据库系统的系统时间,都采用GMT时间,这点是中国程序员需要格外注意的地方,这个可不是标准的北京时间哦。

按照上面的这个GMT时间为基准,中国的标准北京时间只要往前推8个小时就行了。恩,到目前为止,一切顺利,世界和平,挺好。世界上其他地区只要和类似于中国一样的方法,根据GMT时间往前或者往后推若干的小时就行了。但是上面的方法又有一个隐含的前提,就是GMT时间是准确不变的。悲剧的是,GMT时间是依赖英国皇家格林尼治天文台正午时间点的时间系统,这个依赖是个地球运转周期物理级别的依赖。由于地球围绕太阳运转的椭圆形轨道的不匀速运动以及地球本身自转的缓慢减速,于是,于是UTC出现了。(其实确切的说,UT1、UT2是为了修正GMT的最直接产物,那个是更地理上的概念,本文主要介绍计算机系统中经常遇到几个概念,所以忽略UT的概念。)

UTC的英文全称是Coordinated Universal Time,中文翻译为协调世界时,这个奇怪的缩写没有直接采用英文头母的顺序据说是因为英语和法语缩写形式彼此妥协的结果。UTC是以原子时秒长为基础,时刻上尽量接近格林尼治标准时间,可以在时间精度要求不高的情况下,甚至可以将UTC和GMT表示的时间等价对待。不过事实上他们确实不同。UTC中的C是协调的意思,这里主要是为了协调UT1,理论上,UTC和UT1在时刻上的误差不能超过0.9秒,这就要求,UTC实际上需要人为的在某一刻在现有UTC时间的基础上加减一秒(闰秒)来进行调节。至于神马时候来进行加减闰秒的处理,目前在巴黎有个专门的组织叫International Earth Rotation Service来干这个事情。

好了,清楚了UTC的概念之后,前面提到的几个其他没有介绍的缩写就好解释了。现在再来看CST(China Standard Time)、PST(Pacific Standard Time),中文字面翻译分别为中国标准时和太平洋标准时,分别对应的是UTC+8和UTC-8。分别是早于UTC8小时和晚于UTC8小时。对应的,还有很多XST(X为具体的地区的头母缩写),都是基于UTC时区的时间标准。

到目前为止,一切OK。但是欧美人士真是TMD的能折腾,处于对夏季日照时光充分利用,于是他们发明了DST(Daylight Saving Time)这个概念。基本思想就是在夏天白昼时间增长的情况下, 把当地时间人为调快一小时,这样晚上就会有更多的日照时间了。听起来好像有点自欺欺人的感觉,但据说有研究表明,美国人还真因为这个DST省了不少电。。。理解了DST之后,PDT(Pacific Daylight Time)就好理解了,就是在PST基础上调快一小时时间的结果。说白了就是人为的把PST从UTC-8的时区时间改成了UTC-7的时区时间,当然改完了就不叫PST,而是PDT,这个也是西雅图采用的夏令时(Summer Time)标准。

好了,到目前为止,之前列出来的几个缩写都大概介绍完了。但是有句至理名言我们还是不能忘记:“出来混,总是要还的!”

又出啥乱子了呢?

细心的人肯定会注意到,DST的实质是人为的从人们手里“借走”了1小时!就是说你丫的平白无故的就让哥少了一小时,这让是时间如生命的哥情何以堪啊。Ok,所以夏令时一过,你得欠债还钱啊,你得找一天把之前从哥手里拿走的那一个小时还回来。这个时间目前在美国被定为11月第一个周日的凌晨2点钟。就是说到了这个周日的2:00am时,当地时间会瞬间变成1:00am,然后继续往下走,懒人们忽然多了一个小时的睡眠时间。Sounds pretty good,right? 苦逼的程序员伤不起啊,注意了,如果你之前使用了诸如01:15 am PST这类的表达式来控制你的自动运行任务,在这种场景下,你会发现你的任务被自动触发了两次!这个可能完全不是按照你的预期的。这个危险时间段是1:00 am ~ 2:00 am。聪明的你肯定想到了,如果当初借时间的那一刻,刚好会发生相反的事情——你预先定义的一个任务没有运行!因为2:00 am被直接跳成了3:00 am。。。这个危险时间段是在美国实行DST地区的3月第二个周日凌晨的2:00 am ~ 3:00 am。

综合上面的两种case,如果你有一个需要daily自动运行的任务(这个任务必须每天执行,并且必须每天就一次运行),如果使用时区时间是受DST影响的(比如PST,CST就不用care这个问题),那你得格外小心1:00 am ~ 3:00 am这个时间段了。

集中任务调度系统设计的思考

基于上面对于时区、时间、时刻的介绍,我们会发现,对于大型组织的任务调度系统,如下几个基本点必须要考虑:

  1. 集中任务调度系统的必要性:这点我们可以看到,因为时间是基于具体的时区才有意义,而普通Server由于本身设置的不同,可能会采用不同的时区时间。这点就使一些通用的任务调度系统的任务安排如果基于linux本地cron很不稳定(注意:并不是所有的cron都支持时区设置)。于是,一个统一的集中式的任务调度系统就有了他存在必要性。
  2. 集中任务调度系统时间配置语义:这点非常重要。记住:时间是基于时区的!如果你的系统能够确定仅仅只在一个特定是时区context中使用,那就明确好这个约定。如果你是一个庞大的跨国组织公用的系统组件,这个组件必须支持不同时区配置,以方便用户使用。同时,这个也才能真正明确在一个物理的时刻调度一个什么样的任务。这个在系统设计上也应该尽量规避规则本身可能照成的二义性问题,比如上面提到的在受DST影响的地区可能出现的危险时间段:1:00 am ~ 3:00 am。
  3. 任务调度的重叠性考虑:通常这个因素会跟业务运行任务的执行时间紧密相关,如果一个任务的执行时间巨长,直到下一次任务开始运行时他还是没有运行结束,这时必须提供相应的定制选项,由用户来确定如果处理:强行停止上次任务?忽略本次任务?及时给出报警通知?或者。。。

编程语言对时区、时间的支持

有了上面时区、时间的了解,就可以更好的理解编程语言中对这些概念的支持。基本上各大编程语言都在本身或者扩展模块的基础上实现了上述概念。

以Java为例,很多人熟悉的java.util.Date类的一个默认实例,实际上就是以1970年1月1日00:00:00 GMT为基准,到当前时间点(这里说当前时刻应该更合理)的毫秒数。这里可以看出,其实Date实例本身并没有时区的概念,说是一个时刻的概念更合理。

但是需要你需要显示这个时间是,DateFormat接口就需要TimeZone的setter了。原因很简单,时间脱离了时区,就没有意义了。当然你可以不用设置,那么语言本身会默认帮你选择一个默认的系统时区来表示时间(通常这不是一个好的实践)。同样的,Calendar接口中也有相应的时区设置的预留设计。

 

分享到:
评论

相关推荐

    java的时区问题

    Java的时区问题是一个复杂...总的来说,理解和处理Java的时区问题需要对日期时间API有深入的理解,并时刻关注时区数据的更新,以确保程序在全球范围内的准确性和兼容性。同时,合理使用工具和库可以帮助简化这一过程。

    时区和时间

    接下来是“时间”,它包括日期和时刻。在计算机科学中,时间通常以特定格式表示,如ISO 8601(2022-05-07T12:00:00Z),或者用秒或毫秒自UTC以来的偏移量表示。Java编程语言提供了`java.util.Calendar`类来处理日期...

    利用经纬度算日出日落时间

    标题中的“利用经纬度算日出日落时间”是指一种基于地理位置信息,通过数学公式来确定特定地点在特定日期的日出和日落时刻的技术。这种技术对于气象预报、农业规划、户外活动安排以及智能照明系统等领域都有实际应用...

    服务器时区错误1

    在IT行业中,服务器时区错误是一个常见的问题,尤其是在配置数据库连接时。此问题涉及到服务器、数据库管理系统(如MySQL)以及时间...在开发和运维过程中,时刻关注时区处理,可以显著提高系统的稳定性和可维护性。

    javascript+php实现依据用户时区显示当地时间的方法_.docx

    它比较年初和年中同一时刻的时间差,如果相同,则认为没有夏令时。同时,`isEastEarthTime`函数用于判断用户所在时区是在东半球还是西半球。 4. **PHP处理时区转换**: 在服务器端,PHP通过读取JavaScript设置的`...

    dates:使用时刻和时区的日期和时间助手

    "dates:使用时刻和时区的日期和时间助手" 提供了一种高效的方法来管理和操作日期和时间,尤其涉及到时区转换。这个工具可能包含一系列的函数或者类,帮助开发者更轻松地处理复杂的日期和时间计算,比如格式化、比较...

    多时区电子时钟日历软件设计.pptx

    设计目标包括显示年、月、日、时、分、秒和星期,并具备时区设定功能,支持多个时区之间的日期和时间转换。此外,软件还应具备时间调校功能,即使在断电情况下也能保持内部时钟的准确运行。 硬件系统通常由以下几个...

    火车时刻表

    出发时间和到达时间则直接影响乘客的行程安排,要特别注意的是,这些时间通常指的是标准时区的时间,与当地的夏令时可能有所差异。 火车时刻表中还会包含车型信息,如动车、特快、普快等,不同车型的速度、舒适度和...

    java 日出日落时间计算

    开发者可能需要利用`java.time.ZonedDateTime`类来获取当前或特定日期的日期和时间,并结合`java.time.ZoneId`来指定时区。然后,可以使用天文算法,例如“恒星时”或“太阳赤纬”,来计算太阳相对于地平线的位置,...

    GMT时间转成本地时间

    它可以表示特定时刻,并提供了多种方法来解析、格式化和转换日期时间值。`DateTime`类支持两种主要的时间表示方式:`Utc`和`Local`,分别对应于UTC(Coordinated Universal Time,与GMT基本一致)和本地时区的时间。...

    Java时区转换实例代码解析

    因此,同一时刻在不同的时区会有不同的本地时间。 时间通常以格式化的字符串表示,如"2019-11-5 20:05"。然而,这个字符串仅表明了一个相对的本地时间,没有包含时区信息。如果要准确地表示全球通用的时间,需要...

    Java时区转换及Date类实现原理解析

    因此,同一时刻在不同时区表示的时间是不一样的。 二、时间的表示 我们平时表示时间时通常是以一个格式化的字符串来表示一个时间,例如"2019-11-5 20:05"这个字符串表示的是2019年11月5日20点05分。但这里有一个...

    相距时间多久

    总之,计算"相距时间多久"涉及了编程中的日期和时间处理,包括时间戳的获取、时间间隔的计算、数据类型的选取、时区处理和结果的格式化输出。理解这些概念对于编写涉及时间操作的代码至关重要。

    UTC2GMT V1.0(UTC和GMT时间互转)

    总结起来,UTC2GMT V1.0是针对UTC和GMT时间转换需求而设计的实用工具,尤其适用于需要处理跨时区时间信息的IT专业人士。理解UTC和GMT的差异及其在不同场景中的应用,将有助于我们在全球化的信息技术环境中更好地工作...

    Windows 7时间和日期的设置.docx

    5. **添加附加时钟(多时区时间)** - 针对需要与不同时区的人进行交流的情况,Windows 7引入了“附加时钟”功能。这允许您在任务栏上显示其他地区的时间,以便轻松地跟踪不同时区的时刻。 - 要添加附加时钟,进入...

    山东省滨州市邹平实验中学七年级地理下册《第一章 认识大洲 第一节 亚洲及欧洲(时区)》导学案(无答案) 新人教版

    - **地方时**:指的是根据地球上不同地点相对于太阳的位置所确定的时间,每个地方都有其独特的时刻。 - **区时**:为了解决地方时带来的混乱,国际上采用一种统一的时间,即以0经线(格林尼治天文台原址)为基准的...

    秒杀功能js-自定义时间(可不为整点)

    - 使用setTimeout函数,设置定时器在每个时间段的结束时刻触发,然后更新显示的时间段。 3. **实时更新**: - 在前端界面,可以创建一个计时器元素,如HTML的`<span>`或`<div>`,用来显示当前秒杀状态和剩余时间...

    JAVA时间通用集合类

    5. **Duration** 和 **Period**: 分别用于表示两个时刻之间的时间间隔(以秒或纳秒为单位)和日期间隔(年、月、日)。它们可以用于计算两个时间点之间的差距。 6. **TemporalAdjuster**: 用于对日期和时间进行调整...

    JAVA中的时间操作

    6. **Duration**和**Period**: 分别用于表示两个时刻之间的持续时间(以秒和纳秒为单位)和两个日期之间的间隔(年、月、日)。 使用`java.time`包进行时间操作非常直观,例如,创建一个`LocalDate`对象: ```java...

    vb.net 对日期时间的操作实例

    通过`ConvertTime`或`ConvertTimeFrom`方法,可以将一个时区的日期时间转换到另一个时区。 此外,VB.NET还支持日期时间的计算和格式转换。例如,可以使用`DateTime.ParseExact`和`DateTime.TryParse`将字符串转换为...

Global site tag (gtag.js) - Google Analytics