关于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
在Mon Jun 30 23:59:60 UTC 1997
处应该有一个闰秒。
这是否意味着只有date
命令忽略闰秒,而Unix时间的概念不会?
每天的秒数是固定的使用Unix时间戳
Unix时间数在Unix纪元为零,并增加从纪元开始每天86400人
所以它不能表示闰秒。操作系统将减慢时钟以适应这一点。就Unix时间戳而言,闰秒根本不存在。
Unix时间很容易处理,但是有些时间戳不是实时时间,有些时间戳不是唯一时间。
也就是说,有一些重复的时间戳表示时间上的两个不同的秒,因为在unix时间中,第六十秒可能必须重复自己(因为不可能有第六十秒)。从理论上讲,它们也可能是未来的间隙,因为第60秒不一定要存在,尽管到目前为止还没有发布过跳过闰秒。
unix时间的基本原理:它的定义是为了便于使用。向标准库中添加对闰秒的支持是非常棘手的。例如,您希望在数据库中表示2050年1月1日。地球上没有人知道这个日期在UTC还有多少秒!这个日期不能存储为UTC时间戳,因为IAU不知道在接下来的几十年里我们需要增加多少闰秒(它们和随机一样好)。那么,程序员如何进行日期运算呢?因为直到一两年前才知道未来任意两个日期之间的时间长度。Unix时间很简单:我们已经知道2050年1月1日的时间戳(即一年中80年* #秒)。UTC一年到头都很难使用,而unix时间只有在闰秒发生的那一刻才很难使用。
不管怎样,我从来没见过一个程序员同意闰秒。
这里和其他地方有很多关于闰秒的讨论,但这不是一个复杂的问题,因为它与UTC, GMT, UT1, TAI或任何其他时间标准没有任何关系。根据定义,POSIX (Unix)时间是由IEEE Std 1003.1"POSIX"标准指定的时间,可在此处获得。
标准是明确的:POSIX时间不包括闰秒。
协调世界时(UTC)包括闰秒。然而,在POSIX时间(从Epoch开始的秒数)中,闰秒被忽略(不应用),以提供一种简单且兼容的计算时间差的方法。因此,分解后的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(具有指定的epoch),除了他们的原子钟之外,没有人需要联系任何人。然而,我们没有这样做,可能是因为我们希望POSIX时间戳是UTC时间戳。
利用POSIX标准中一个明显的漏洞,实现故意减慢或加快秒-以便POSIX时间不再使用SI秒-以便与UTC时间保持同步。阅读标准可以清楚地看出,这并不是标准的本意,因为这不能在孤立的系统中完成,因此不能与其他机器互操作(它们的时间戳,如果没有闰秒,对于其他机器来说意味着不同的东西,如果有闰秒)。读:
[…重要的是,时间名称和秒的解释,因为Epoch值在一致的系统中是一致的;也就是说,重要的是,所有符合标准的系统将"536457599秒since the Epoch"解释为59秒59分23小时1986年12月31日,而不管系统当前时间概念的准确性。给出表达式是为了确保一致的解释,而不是试图指定日历。[…这个未指定的秒在名义上等于国际系统(SI)秒的持续时间。
允许此行为的"漏洞":
注意,作为这样做的一个实际结果,由某些外部标准测量的秒的长度没有指定。
因此,实现通过有意地将其更改为不能在孤立的或非参与的系统之间互操作的东西来滥用这种自由。或者,实现可以简单地重复POSIX多次,就好像没有时间过去一样。有关所有现代实现的详细信息,请参阅Unix StackExchange回答。
哎呀,这让人很困惑……一个真正的脑筋急转弯!
由于其他两个答案都包含许多误导性信息,所以我将把这个添加进去。
Thomas是对的,Unix Epoch时间戳每天的秒数是固定的。这意味着在有闰秒的日子里,午夜前的第二秒(午夜前UTC分钟的第61秒)被赋予与前一秒相同的时间戳。如果你愿意的话,这个时间戳是"重播"的。因此,相同的unix时间戳将用于现实世界中的两秒。这也意味着,如果您得到unix epoch的分数,那么整个秒将重复。
X86399.0
, X86399.5
, X86400.0
, X86400.5
, X86400.0
, X86400.5
,然后X86401.0
。
所以unix time不能明确地表示闰秒——闰秒时间戳也是前一个真实世界秒的时间戳。