关于闰秒

关于闰秒

2012年6月30日,也就今天晚上,时间会多出现一秒,也就是我们所说的闰秒。我不知道大家对闰秒的了解有多少,所以写下这篇文章。

背景知识

闰秒是在在UTC(中文“世界标准时间”或“世界协调时间/英文“Coordinated Universal Time”/法文“Temps Universel Cordonné”)是基于Atomic Clock(原子时钟)的一种时间,向太阳时(Solar Time )对齐的一种方法,因为太阳时是根据地球公转来计算的。所以,1972年制定的UTC为了确保其时间相对于UTC的时间误差不能超过0.9秒,因此在过一段时间后需要加一秒。下图是有UTC以来闰秒的调整表(来自Wikipedia闰秒的中文词条

从上表中我们可以看到,从1972年到现在,在这四十年里已经进行过25次的闰秒调整。闰秒是在每年6月或12月的最后一天的最后一分钟进行跳秒或不跳秒。是否加入闰秒由位于巴黎的国际地球自转和参考坐标系统服务(IERS – International Earth Rotation and Reference Systems Service)决定。如果决定加入闰秒,那么这一秒是被加在第二天的00:00:00前的,也就是说,时间会出现23:59:60的情况,然后才是第二天的00:00:00。如果是负闰秒的话,23:59:58的下一秒就直接跳到第二天的00:00:00了。现在,所有闰秒都是正闰秒

计算机处理闰秒

那么,对于我们的电脑系统来说,怎么处理这个闰秒呢?一般来说,我们需要为我们的电脑系统配置UTC时钟,并通过NTP (Network time protocol)来进行时间同步,NTP服务器会一级一级地下发闰秒事件通知直到最边缘的NTP服务器,然后NTP服务器就会把闰秒通知发给客户端的操作系统,由操作系统来处理闰秒通知。

虽然闰秒调整对普通民众的日常生活不会产生影响。不过,这个问题将影响部分开启ntp服务的Linux操作系统——会导致Linux内核Crash!Linux kernel是在2.6.18-164.e15之后的版本中解决了这个问题。换句话说,Linux kernel低于2.6.18-164的Linux系统,无论是什么公司的Linux都将受到影响。(今晚过后大家可以查看一下你的Linux系统日志,看看闰秒有没有发生)

可以参看下面的bug描述:

那么,我们的操作系统是怎么处理正闰秒通知的?通常来说有三种实现:

  1. 后退一秒。
  2. 停止一秒。
  3. 真正的增加一秒。

懂编程的人一眼就能看出来,前两种方式是以一种Workaround或Hack的方式解决这个问题。第一种方式会导致一些基于timestamp的消息通知乱序了,而第二种会导致出现两个一模一样的timestamp。最后一种不会出现timestamp的问题。对了,你还记得以前那篇《你确信你了解时间吗?》的文章吗?

最后,说说Windows,Windows  Time Service不支持闰秒通知,所以,当闰秒发生的时候,你的Windows上的时间会比实际时间快一秒钟,这需要等下一次的时钟同步才会完成修正。你可以查看这篇文章:http://support.microsoft.com/kb/909614/en-us

(全文完)

(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)

好烂啊有点差凑合看看还不错很精彩 (12 人打了分,平均分: 4.00 )
Loading...

关于闰秒》的相关评论

  1. 闰秒是全球同步修改,所以北京时间是在 7.1 07:59:60,而不是在6.30 的 23:59:60

  2. 今日时间多一秒 7:59:60你感觉到了吗? 由于地球自转速度减慢…
    如果需要精确到1秒的应用系统,而且设备是非联网更新的,则肯定乱套了。。。。
    记得军阀时代,曾经漏了一天还是多少,这样就要求做IT系统的标准日期系统,还要懂得历史天文的人为增减事件了,的确不合理

  3. 另外,很多系统(ms sql server、delphi应用等)的时间类型值,其实是距某个特定时间点(如1900-01-01、1970-01-01)的秒数
    如果有这么多不规则的闰月,而且很多是事后才人为添加的,那些系统肯定无法预先知道,事前的闰月,估计一般也不会考虑进行的
    所以,美国要求取消闰秒机制,应该是合理的

  4. 如果不计算闰秒累计几千年下去就会出现黑白颠倒季节错乱吧。
    坐在办公室里编个代码,还得考虑地球公转自转的变化……

    xkcd发明了EST来解决这个问题
    http://xkcd.com/1061/

  5. 您好,我对操作系统处理闰秒的方式还不太明白:
    1、操作系统提供了年月日时分秒与时间戳的相互转换的函数,这种转换有没有考虑闰秒?如何考虑闰秒?
    2、假如我的电脑没有运行NTP,我只是通过其他方法把年月日时分秒调对了,再问问题1。
    我对计算机懂的不多,希望大牛答疑解惑。

  6. windtear :
    这篇文章有些东拼西凑 错误太多了

    我特别不喜欢这样的评价,显得自己很高深的样子.

    如果直截了当指出某处某处硬伤,佩服之至.
    “乃水平太次,错误太多,不屑置辩~”呵呵

  7. @Walkerinwind

    比如背景这一段 完全乱七八糟啊
    “闰秒是在在UTC向Atomic Clock(原子时钟)对齐的一种方法,因为UTC是民用时间,其精确值是毫秒,而Atomic Clock精确值是纳秒,所以,1972年制定的UTC为了确保其时间相对于Atomic Clock的时间误差不能超过0.9秒,因此在过一段时间后需要加一秒。”
    如果参考维基百科中文版 应该是:“在协调世界时 (UTC) 中增加或减少一秒,使它与平太阳时贴近所做调整。UTC,是透过广播作为民用时的官方时间基础,它使用非常精确的原子钟来维护。要保持UTC与平太阳时的一致性,偶尔需要调整”
    在这个意义上 UTC和原子时种可以理解为是一回事 闰秒UTC是因为相对于mean solar time,不是UTC相对于原子时。

    后面的也是以讹传讹
    “换句话说,Linux kernel低于2.6.18-164的Linux系统,无论是什么公司的Linux都将受到影响。”
    传说的错误是“RHEL 5.4 2.6.18-164以下 RHEL 4.8 2.6.9-89以下” (其实也并不受到影响) 其他公司用官方2.6.18压根都没引入这个错误呢

    处理闰秒三种实现的解释那段也是乱七八糟
    可以参考这里 http://www.eecis.udel.edu/~mills/leap.html

    另外这篇拼凑文章只提了先前网上误传的老版本的问题 也没有指出新版本的问题
    可以参考这里
    http://it.slashdot.org/story/12/07/01/1920217/leap-second-bug-causes-crashes
    http://serverfault.com/questions/403732/anyone-else-experiencing-high-rates-of-linux-server-crashes-during-a-leap-second

    1. @windtear, 谢谢批评。

      1)背景的一段是我理解错误的问题,我把太阳时理解成了原子钟,我已修正。

      2)关于实现的三种方式没问题,那就是Unix/Linux下的三种不同的实现方式,你可以查看Leap Second Handling by Operating Systems

      3)关于你说的Linux的内核受影响的问题,给你两个内核的commit log
      NTP: remove clock_was_set() call to prevent deadlock

      ntp: Fix leap-second hrtimer livelock

      另,你的评论没有被批准是因为你的评论中有很多链接,所以被系统识别为可能为垃圾评论。

  8. 最近看了楼主的很多文章,感觉学到了很多,在此地无其他表示感激的方式,只能真心地说句谢谢。

  9. 其实,博文本身对与错肯定是有争议的,再好的文章,想找漏洞也是能找到,我觉得博文最大的好处,就是能通过分享带动一股热潮,带来一些评论,带来不一样的观点。就好像,博主曾经对c情有独钟,对Java的认识可能也有些许的偏见(当然,博主后来貌似已经摒弃了语言之间的门阶),但是热爱java的人看了博主的文章,会引发不一样的思考,会引起java之人对c、unix、linux产生某中好奇,会让人发问:unix c真就这么强大吗?其实,这无形之中就已经带来了社会效应。所以,顶coolshell,期待博主的好文章。

  10. @陈皓
    3)关于你说的Linux的内核受影响的问题,给你两个内核的commit log
    commit 1 -> NTP: remove clock_was_set() call to prevent deadlock
    commit 2 -> ntp: Fix leap-second hrtimer livelock
    没做过内核还是不要谣传这类的比较好。。。
    对commit 1, 老版本的内核没有打开HRTIMER, clock_was_set() 是空函数
    对commit 2,是由于commit 7dffa3c673fbcf835cd7be80bb4aec8ad3f51168引起的regression,而那个commit是的3.x里引入的
    leap second的bug只有在2.6.26-26.27内核才会出现

  11. 楼主,那么java和c#为啥没有闰秒呢,我用java写Date(2012, 5, 30, 23, 59, 59)得到的是6月31号的0点,Date(2012, 6, 1, 7, 59, 60)得到的是7月1日8点钟;用c#的话new DateTime(2012, 6, 30, 23, 59, 60)和new DateTime(2012, 7, 1, 7, 59, 60)都会报错。
    程序里不能出现60秒吗?

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注