Unix时间和闰秒

60
关于Unix(POSIX)时间, 维基百科 表示:

由于它对闰秒的处理方式,它既不是时间的线性表示,也不是UTC的真实表示。

但是Unix的date命令似乎并不知道它们存在。
$ date -d '@867715199' --utc
Mon Jun 30 23:59:59 UTC 1997
$ date -d '@867715200' --utc
Tue Jul  1 00:00:00 UTC 1997

在1997年6月30日23:59:60 UTC应该有一个闰秒。

这是否意味着仅有date命令会忽略闰秒,而Unix时间的概念没有忽略?


9
这里有一个关于UTC/TAI的好总结,网址是http://www.madore.org/~david/computers/unix-leap-seconds.html。 - loreb
2
本页面说明操作系统如何处理/应该如何处理来自ntp的闰秒信息,请参阅https://www.meinbergglobal.com/english/info/leap-second.htm#os - Silver Moon
“Mon Jun 30 23:59:60 UTC 1997.” 毫无意义。这是一个无效的时间。 - Sebi2020
2
IANA时区信息:https://www.iana.org/time-zones 当前IETF闰秒列表:https://raw.githubusercontent.com/eggert/tz/main/leap-seconds.list 注意!该文件中的十六进制编码SHA-1哈希省略了前导零。 - PM 2Ring
1
@Sebi2020 这是有道理的,因为这就是插入闰秒的地方。 - undefined
4个回答

43

每天的秒数是通过Unix时间戳固定的。

Unix时间戳从Unix时期开始为零,自时期以来每天增加确切的86400。

因此它不能表示闰秒。操作系统会减慢时钟以适应此问题。就Unix时间戳而言,闰秒根本不存在。


3
Unix秒可以与“实际”秒不同。 Unix日有86400秒,实际上有86401秒(对于带闰秒的日子)。否则,时钟会像TAI一样超前:TAI比UTC超前35秒。这35秒来自于1972年初开始的初始差异为10秒以及自1972年以来UTC中的25个闰秒。 - Thomas Jung
9
@ThomasJung,你的答案有误导性/错误。 1)Unix时间可以并且确实表示闰秒,尽管不是明确的。例如,UTC 1998-12-31 23:59:60.25被表示为Unix时间915148800.25。如果使用Unix时间戳固定秒数,则每天将有86400个唯一的整数Unix时间戳。尽管Unix时间戳每天增加86400,但这并不意味着我们每天拥有86400个Unix时间戳秒数。由于负闰秒,不是每个实数都是有效的Unix时间戳,也不是每个实数... - Pacerier
4
  1. 数字是一个独特的Unix时间戳,由于正闰秒而产生。
  2. 就Unix时间戳而言,确实存在闰秒。如果不存在,Unix时间将在闰秒期间冻结,但实际上并没有这种情况发生。
- Pacerier
2
@Campa:TAI时间在闰秒期间仍像往常一样持续推移(每个闰秒都会增加 TAI - UTC 差异)。 POSIX时间是UTC时间(不包括闰秒的那些时刻)。TAI可以告诉实际经过的UTC(国际原子时)秒数,POSIX则是UT(地球自转)秒数(因为UTC与UT相差不超过0.9秒)。要找出两个以UTC表示的事件之间经过了多少实际秒数,您需要知道每个事件的对应闰秒数量,例如2010-01-01——34个闰秒,2013-01-01——35个闰秒。 - jfs
4
以下是来自 POSIX 规范的权威答案链接:http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_15 引用如下:“在 POSIX 时间(自纪元以来的秒数)中,闰秒被忽略(不适用)”。 - Kenton Varda
显示剩余13条评论

36

Unix时间易于处理,但有些时间戳不是真实时间,有些时间戳也不是唯一的时间。

也就是说,在unix时间中有一些重复的时间戳代表了两个不同的时间秒,因为在unix时间中第60秒可能必须重复(因为不能存在第61秒)。从理论上讲,未来也可能存在间隔,因为第60秒并不需要存在,尽管迄今为止还没有跳过闰秒。

Unix时间的理由是:它被定义为易于处理。向标准库添加对闰秒的支持非常棘手。例如,您想在数据库中表示2050年1月1日。地球上没有人知道那个日期与UTC相差多少秒!不能将日期存储为UTC时间戳,因为国际天文联合会不知道我们在未来几十年内需要添加多少闰秒(它们几乎是随机的)。那么在未来任意两个日期之间经过的时间长度要到一两年前才知道,程序员该如何进行日期运算?Unix时间很简单:我们已经知道2050年1月1日的时间戳了(即80年*每年秒数)。UTC全年都非常难以处理,而Unix时间只在发生闰秒的瞬间难以处理。

值得一提的是,我从未遇到过赞成闰秒的程序员。他们应该被废除。


4
不,Unix时间从不包含闰秒。它与协调世界时(UTC)同步,也就是说,在UTC滴答声时,Unix时间也会滴答声:一秒钟的长度完全相同,并且它们对齐。有时当Unix时间滴答声时,其值会增加两个,而UTC只会增加一个。与任何具有闰秒的系统相比,Unix时间要简单得多,因为闰秒实在是一个彻头彻尾的玩笑。 - Nicholas Wilson
6
抱歉,上个评论里有个愚蠢的错误。第三句话应该这样写:“有时候当Unix时间戳达到下一秒时,它的值会重复上一秒,而UTC时间则始终仅增加一秒。” - Nicholas Wilson
6
好的,2050年1月1日00:00:00对应的Unix时间戳是2524629600。但是它对应的UTC时间戳是未知的。这对程序员来说是一个大问题:要么写很多代码,要么做一些非常粗糙的编程(根据软件需要遵守的任何规定,这甚至可能不合法)。由于我们不知道闰秒何时到来,所以它们几乎是随机的。我们没有任何模型能够精确地预测地球的摆动,我们只能每年等待并观察。当然,它是确定性的,但这对程序员或国际天文学联合会都没有帮助。 - Nicholas Wilson
3
我已删除了我的评论。你赢了。如果你想学习,就从学习概率分布开始。 - jfs
4
是的,这是显而易见的实现方式。但它有一个令人讨厌的后果,每年在时钟调整时,你的计算机时钟将与世界时间相差数百毫秒长达几分钟。需要保持稳定秒针的应用程序会受到干扰(尽管它们当然应该使用单调时钟),需要准确的世界时间的应用程序也会受到干扰。但是没有合理的替代方案...结论是:无论你忽略还是考虑闰秒,它们都是不好的。 - Nicholas Wilson
显示剩余16条评论

33
这里和其他地方都有很多关于闰秒的讨论,但这并不是一个复杂的问题,因为它与UTC、GMT、UT1、TAI或任何其他时间标准无关。 POSIX(Unix)时间按照IEEE Std 1003.1“POSIX”标准定义,此处提供。

该标准是明确无误的:POSIX时间不包括闰秒。

协调世界时(UTC)包括闰秒。 但是,在POSIX时间(自纪元以来的秒数)中,忽略闰秒(未应用)以提供计算时间差的简便和兼容方法。 因此,POSIX时间可能并不是UTC,尽管外观相似。

该标准详细说明了POSIX时间不包括闰秒,特别是:

强制要求符合实现必须与任何特定官方时钟具有固定关系(考虑孤立系统或通过设置时钟到某个任意时间执行“重新运行”的系统)是一个实际上不可能的事情。

由于闰秒是由委员会决定的,因此在POSIX时间中包括闰秒不仅是一个“坏主意”,而且还不可能,因为该标准允许符合规范的实现没有网络访问权限。
在这个问题中,@Pacerier已经说过POSIX时间包括闰秒,并且每个POSIX时间可能对应多个UTC时间。虽然这确实是POSIX时间戳的一种可能解释,但这绝不是标准规定的。他的观点很大程度上只是空话,并不适用于定义POSIX时间的标准。
现在,事情变得复杂了。按照标准规定,POSIX时间可能与UTC时间不等价:
“因此,分解的POSIX时间并不一定是UTC时间,尽管它看起来是。”
然而,在实践中,它确实是。为了理解这个问题,你必须了解时间标准。GMT和UT1基于地球在宇宙中的天文位置。TAI基于宇宙中物理(原子)反应测量的实际时间流逝量。在TAI中,每秒都是一个“SI秒”,它们的长度完全相同。在UTC中,每秒也是一个SI秒,但根据需要添加闰秒,以将时钟重新调整到GMT / UT1的0.9秒以内。GMT和UT1时间标准是通过测量地球在宇宙中的位置和运动来定义的,这些经验性测量不能通过任何手段(科学理论或近似)预测。因此,闰秒也是不可预测的。
现在,POSIX标准还规定了一个意图,即所有不同实现中的POSIX时间戳应该是可互操作的(意味着相同)。一种解决方案是让每个POSIX秒等于一个SI秒,这样POSIX时间就等同于TAI(使用指定的纪元),除了原子钟以外,没有人需要联系任何人。然而,我们并没有这样做,可能是因为我们希望POSIX时间戳成为UTC时间戳。
利用POSIX标准中的一个明显漏洞,实现有意减慢或加快秒数--以便POSIX时间不再使用SI秒--以保持与UTC时间同步。阅读标准清楚地表明这不是预期的结果,因为这不能用于孤立系统,因此它们无法与其他机器互操作(它们的时间戳,没有闰秒,对于具有闰秒的其他机器来说意义不同)。
"漏洞"允许这种行为:
请注意,作为这种情况的实际后果,由某些外部标准测量的一秒钟长度未得到指定。
因此,实现机构通过有意将其更改为在隔离或非参与系统之间不能互操作的内容来滥用这种自由。或者,实现可能只是重复POSIX时间,就好像没有时间流逝一样。有关所有现代实现的详细信息,请参见此Unix StackExchange答案
哎呀,那真是令人困惑...真是个脑力挑战!

你的意思是“在协调世界时,每秒都是国际单位制中的一秒,但必要时会减去闰秒…” - Carlo Wood
我认为UNIX时间应该被解释为一种想象的系统,在这个系统中,地球按照国际原子时(TAI)进行神奇的旋转。忽略闰秒并且从UNIX时间戳计算的时间差如果包含闰秒,则与单调SI兼容秒中的实际间隔不匹配。对于不包含闰秒的时间段,UNIX时间完全匹配SI秒。在闰秒期间,UNIX系统会逻辑上停滞一秒,并且在实践中,在闰秒期间生成的时间戳将重复前一秒。 - Mikko Rantalainen
我认为UNIX时间应该被解释为一个想象中的系统,其中地球根据国际原子时(TAI)进行神奇旋转。闰秒被忽略,如果时间间隔包含闰秒,则从UNIX时间戳计算的时间差与单调的国际单位秒实际间隔不匹配。对于不涉及闰秒的时间段,UNIX时间完全与国际单位秒相符。在闰秒期间,UNIX系统逻辑上会停顿一秒钟,并且在实践中,在闰秒期间生成的时间戳将重复前一秒的时间。 - Mikko Rantalainen

11

由于其他答案中包含大量误导信息,我会提供以下内容。

Thomas说每天Unix纪元时间戳秒数是固定的。这意味着在有闰秒的那天,午夜前一秒钟(午夜前UTC分钟的第61秒)被赋予与前一秒相同的时间戳。

如果你将获取到的 Unix 纪元时间戳转换为日期和时间,则这个时间戳就像被“重放”了一样。因此,在现实世界中会有两秒钟使用相同的 Unix 时间戳。这也意味着,如果获取的Unix时间戳带小数部分,则整数部分所代表的秒数将被重复。

X86399.0, X86399.5, X86400.0, X86400.5, X86400.0, X86400.5, 然后是 X86401.0

因此,Unix时间不能 明确地 表示闰秒 - 闰秒时间戳也是前一个真实世界秒的时间戳。


4
这也意味着短语“自纪元以来的秒数”是极其误导人的。那些不是国际单位制中的秒,而是某种神秘的、没有精确定义的“POSIX秒”,随着越来越多的闰秒(或多或少地)被应用,它们的长度也会发生变化。 - Carlo Wood
2
@CarloWood 这是自1970年以来的秒数。其中一秒被定义为一天的1/86400。要获取SI秒中自1970年以来的确切秒数,您需要添加由UTC定义的闰秒。这并不难理解。 - Gellweiler
3
@Gellweiler 我完全理解:P。我只是澄清一下,当他们说“自纪元以来的秒数”时,他们并不是在谈论真正的(S.I.)秒,而仅仅是返回“分数天数乘以86400”的数量-这未能给出自某些天以来的真正秒数,因为有些天是86401秒。但是,如果您确切地知道何时添加了闰秒,则可以更正结果-因此对于过去它们并不是“神秘的”。但是,对于未来来说,它们有点神秘,因为我认为闰秒将永远不会被固定添加。 - Carlo Wood
2
当有人无法看到某个主题的复杂性时,却说“这并不难理解”,我总是感到沮丧。 - B T
这个答案认同以下观点:“在闰秒期间增加系统时钟并在闰秒结束时将时钟向后调整一秒。这是 POSIX 采取的方法。” --https://www.eecis.udel.edu/~mills/leap.html - Andrew
如果您将纪元考虑为迄今为止增加的闰秒总数的函数而不是常数,则不会产生误导。 “实际上,每次新增闰秒后都会重新建立新的时间刻度。因此,在建立每个新的时间刻度时,所有以前的闰秒,更不用说时间刻度本身的表象起源,都会向后突进一秒钟。” --https://www.eecis.udel.edu/~mills/leap.html - Andrew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接