关于闰秒
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描述:
- LKML: Chris Adams: Re: Bug: Status/Summary of slashdot leap-second crash on new years 2008-2009
- Bug 479765 – Leap second message can hang the kernel
那么,我们的操作系统是怎么处理正闰秒通知的?通常来说有三种实现:
- 后退一秒。
- 停止一秒。
- 真正的增加一秒。
懂编程的人一眼就能看出来,前两种方式是以一种Workaround或Hack的方式解决这个问题。第一种方式会导致一些基于timestamp的消息通知乱序了,而第二种会导致出现两个一模一样的timestamp。最后一种不会出现timestamp的问题。对了,你还记得以前那篇《你确信你了解时间吗?》的文章吗?
最后,说说Windows,Windows Time Service不支持闰秒通知,所以,当闰秒发生的时候,你的Windows上的时间会比实际时间快一秒钟,这需要等下一次的时钟同步才会完成修正。你可以查看这篇文章:http://support.microsoft.com/kb/909614/en-us
(全文完)
(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)
《关于闰秒》的相关评论
对于普通用户来说,`sudo ntpdate cn.pool.ntp.org` 应该就可以了。
生产环境里一坨子RHEL4呢。。。不少还是关键服务器
不说这事都要忘记了。。。
弱弱的问一句:我觉得还是windows的办法强,有和我同感的么?
刚Google Reader上看到…
真是应景的文字
闰秒是全球同步修改,所以北京时间是在 7.1 07:59:60,而不是在6.30 的 23:59:60
一个是北京时间,一个是世界时间,二者等同@steedguo
链接的网页是Google Blog中介绍Google是如何处理闰秒的。
真不知道闰秒的事情会这么频繁啊。
明天去公司看看是否有这方面的。
今日时间多一秒 7:59:60你感觉到了吗? 由于地球自转速度减慢…
如果需要精确到1秒的应用系统,而且设备是非联网更新的,则肯定乱套了。。。。
记得军阀时代,曾经漏了一天还是多少,这样就要求做IT系统的标准日期系统,还要懂得历史天文的人为增减事件了,的确不合理
另外,很多系统(ms sql server、delphi应用等)的时间类型值,其实是距某个特定时间点(如1900-01-01、1970-01-01)的秒数
如果有这么多不规则的闰月,而且很多是事后才人为添加的,那些系统肯定无法预先知道,事前的闰月,估计一般也不会考虑进行的
所以,美国要求取消闰秒机制,应该是合理的
@haitao
上面的闰月,应该都是闰秒
如果不计算闰秒累计几千年下去就会出现黑白颠倒季节错乱吧。
坐在办公室里编个代码,还得考虑地球公转自转的变化……
xkcd发明了EST来解决这个问题
http://xkcd.com/1061/
您好,我对操作系统处理闰秒的方式还不太明白:
1、操作系统提供了年月日时分秒与时间戳的相互转换的函数,这种转换有没有考虑闰秒?如何考虑闰秒?
2、假如我的电脑没有运行NTP,我只是通过其他方法把年月日时分秒调对了,再问问题1。
我对计算机懂的不多,希望大牛答疑解惑。
这篇文章有些东拼西凑 错误太多了
@pete
几千年也就差1小时最多了。不用一百年,就完全可以有更好的解决办法了
学习了
我特别不喜欢这样的评价,显得自己很高深的样子.
如果直截了当指出某处某处硬伤,佩服之至.
“乃水平太次,错误太多,不屑置辩~”呵呵
小小的一秒钟竟然有这么深的东西
@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
@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
另,你的评论没有被批准是因为你的评论中有很多链接,所以被系统识别为可能为垃圾评论。
@Walkerinwind
我18:16评论了几段 1.2k 管理员还没审核通过
最近看了楼主的很多文章,感觉学到了很多,在此地无其他表示感激的方式,只能真心地说句谢谢。
其实,博文本身对与错肯定是有争议的,再好的文章,想找漏洞也是能找到,我觉得博文最大的好处,就是能通过分享带动一股热潮,带来一些评论,带来不一样的观点。就好像,博主曾经对c情有独钟,对Java的认识可能也有些许的偏见(当然,博主后来貌似已经摒弃了语言之间的门阶),但是热爱java的人看了博主的文章,会引发不一样的思考,会引起java之人对c、unix、linux产生某中好奇,会让人发问:unix c真就这么强大吗?其实,这无形之中就已经带来了社会效应。所以,顶coolshell,期待博主的好文章。
@holyghost
同感
@陈皓
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内核才会出现
长见识了
Hi, I read your blogs like every week. Your story-telling style is awesome, keep it up!
楼主,那么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秒吗?
我为祖国续一秒