UTC 1972-06-30 23:59:59 = 78796799 seconds since epoch
UTC 1972-06-30 23:59:60 = 78796800 seconds since epoch
UTC 1972-07-01 00:00:00 = 78796800 seconds since epoch
UTC 1972-07-01 00:00:01 = 78796801 seconds since epoch
这意味着要么自纪元以来的那些“秒”的长度(物理上)并不相同,要么纪元本身实际上“移动”。随你挑选。
如上所述,一秒是两(物理,SI / UTC)秒长,所以显然它们的长度并不相同。
如果您采用“所有天都是 86400 秒”的定义,假设长度恒定的 SI 秒并对此进行回溯,则纪元“移动”如下所示。(也就是说,由于 UTC 1972-07-01 00:00:00 是 UTC 1970-00-01 00:00:01 之后的 78796800 SI 秒,因此它必须是当时的有效纪元。)
好吧,他们确实用“大约”来对冲。
(“一天中的实际时间与自纪元以来的当前秒数之间的关系未指定。”这句话本身很奇怪,因为几乎所有实际目的 UTC 都是“一天中的实际时间”,并且定义上面依赖于 UTC。我不确定它指的是什么,但这可能只是意味着系统时钟不需要准确。而且,如果没有外部同步,大多数计算机时钟都不需要。
date
Sat Oct 14 17:17:59 BST 2023
date +'%s'
1697300279
date --date '@1697300279'
Sat Oct 14 17:17:59 BST 2023
date --date '@1697300279' +'%Y-%m-%d %H:%M:%S'
2023-10-14 17:17:59
这就是定义,是的。
你并不是唯一的一个。这是一个搞笑的混乱。
是的,见下文。
是的。
事实并非如此。它实际上闭上了眼睛,拒绝听任何关于这种尴尬和不切实际的技术问题的讨论。
“自纪元以来的秒数”的 POSIX 定义基于细分的 UTC 时间,明确假设所有日期的长度均为 86400 秒:
( 的奇数处理
tm_year
是为了考虑闰日;除法是截断整数除法。)基本原理部分直接承认忽略闰秒:
上面的表达式意味着当插入闰秒时,“自纪元以来的秒数”会重复一整秒:
这意味着要么自纪元以来的那些“秒”的长度(物理上)并不相同,要么纪元本身实际上“移动”。随你挑选。
如上所述,一秒是两(物理,SI / UTC)秒长,所以显然它们的长度并不相同。
如果您采用“所有天都是 86400 秒”的定义,假设长度恒定的 SI 秒并对此进行回溯,则纪元“移动”如下所示。(也就是说,由于 UTC 1972-07-01 00:00:00 是 UTC 1970-00-01 00:00:01 之后的 78796800 SI 秒,因此它必须是当时的有效纪元。)
好吧,他们确实用“大约”来对冲。
(“一天中的实际时间与自纪元以来的当前秒数之间的关系未指定。”这句话本身很奇怪,因为几乎所有实际目的 UTC 都是“一天中的实际时间”,并且定义上面依赖于 UTC。我不确定它指的是什么,但这可能只是意味着系统时钟不需要准确。而且,如果没有外部同步,大多数计算机时钟都不需要。
同样,“因此,尽管出现了 POSIX 时间,但其具体时间并不一定是 UTC。” 基本原理部分看起来很奇怪,但适用于闰秒。否则给定的等价似乎没问题。)
但不要指望我能把它弄对,因为聪明的人已经写了足够多的文章了。
Alex Chan简要介绍了程序员对 Unix 时间的误解。
SE 帖子Unix 时间和闰秒包含一些讨论,并链接到David Madore 发表的听起来令人信服的帖子“Unix 闰秒混乱” 。
那个提到了在 NTP 中处理这个问题,红帽开发者博客中有五种不同的方法来使用 NTP 处理闰秒。
其中一种方法当然是 Google在 2008 年开始使用的“leap smearing”。 (强制 XKCD)
Unix 时间的维基百科页面有一个与上面类似的表格,显示了重复值,同时还包括 TAI 和 UTC。
取决于具体是哪几秒......
如果是 Unix 时间,除以 86400 即可得到天数,然后遵循有关可变长度月份、闰日和时区的通常规则。
或者更确切地说,打电话
localtime()
或gmtime()
为您做这件事。如果是其他时间,请使用一些可以处理您所拥有的内容的库。
您混淆了多个概念。UNIX 时间(从足够的高度来看)是一个秒计数器,这只是一个本地概念。最后,有人拿着一个时钟给你说“根据这个漂亮的时钟,现在距离 1970 年 1 月 1 日已经过去了多少秒”,你就说“好吧,那么现在距离 1970 年 1 月 1 日已经过去了多少秒” ”并继续数秒。这对于许多“家庭”计时用途来说是可以的,例如,存储您上次更改日记文档的时间。TAI也只是一个秒计数器,但它是一个协调的计数器,这意味着它不仅仅是本地的时间计数,而是许多原子钟的平均值。
UTC 是完全不同的东西:它定义了现在的时间,而不仅仅是自某个常见事件以来的秒数。
例如,在许多情况下,“自纪元以来已有一千四百二十万二十六秒”不如说“这里是早上 9 点 12 分,今天是六月六号”有用。
需要明确的是:“UNIX 时间”只是自特定事件(纪元)以来经过的秒数。如果您有一个每秒滴答一次的完美节拍器,并且您计算了自该日期以来的滴答数,那就是 UNIX 时间。(如果不是因为这个计数器实际上是从 UTC 派生的,每次 UTC 插入闰秒时,该计数器都会有效地将纪元向前移动一秒。)
现在,您的困惑源于这样一个事实:例如 1697300527(这是几秒钟前的 UNIX 时间)对于人类来说并不是一个非常有用的时间。您需要将第二个计数转换为人类可读的日期时间(例如,2023 年 10 月 14 日星期六 18:22:01)。
时间转换当然必须考虑闰年、闰秒、时区和其他修正。这意味着从 UNIX 时间到 UTC 时间或任何其他时间表示形式的转换不一定是平滑、连续的,甚至是明确的。(例如:可能有多个 UNIX 时间戳对应于您所在时区夏令时结束当天的凌晨 3:15。)
就是这样。虽然您总是可以“轻松且明确地”说“自纪元以来现在已经有这么多秒了”,但只需计算从那时起的秒数(这就是 UNIX 时间),即可转换为本地时间(或协调时间)出于人类目的的表示可以是非单调的。
通过使用您的平台拥有的时区信息。Chris Davies 建议使用
date
,我同意。任何合理的编程语言 都可以访问 tzinfo 数据库。1 C:
ctime(…)
、C++:、std::chrono
Python:python -c 'import datetime;print(datetime.datetime.now())'
、Perl、Haskell,...)如果您有合适的版本,
date
则可以使用其内置功能: