我刚刚发现 Unix 时间不包括闰秒。我认为这很令人惊讶,因为这样做会慢慢偏离 UTC ……但这不是我的问题的重点。
编辑(3x):简而言之,更多讨论见下文和评论:
假设系统时钟遵循 Unix/POSIX 时间(不是“真正的”UTC),如何获得自 Unix 纪元(来自date
或任何其他程序)以来经过的实际秒数?
或者,至少,Linux 中是否有“闰秒”文件,我可以在其中获得闰秒而无需手动下载它们?
关于我如何得出系统时钟设置为 Unix 时间的结论的说明:
因此,为了最精确地确定相对于历史公历和 UTC 时间标度的纪元,用户必须从表观的 NTP 或 POSIX 纪元中减去IERS 提供的相关偏移量。
关于我如何得出date --utc +%s
真正给出我们所谓的“Unix 时间戳”的结论的解释:
第一个闰秒是在 1972 年 6 月 30 日引入的。
从 1970 年 1 月 1 日 00:00:00(Unix 纪元)到 1972 年 7 月 1 日 00:00:00,我们可以轻松计算出有 365 + 365 + (31+29+31+30+31+30) 天 + 1闰秒 = 912 天 + 1 闰秒 = 78796801 秒。现在尝试date -R --utc -d @78796801
...输出:Sat, 01 Jul 1972 00:00:0 1 !! 如果您认为(正如我之前所做的那样)Unix 时间戳直接给出了自 1970 年 1 月 1 日 00:00:00 以来我们现实世界中经过的秒数……那是错误的!
本例证明将date
后的值@
视为真正的 Unix 时间戳,并按照 POSIX 时间定义给出正确的对应日期。但是如何使用相同的值并说这不是时间戳而是自纪元以来的实际秒数?...
[不要阅读以下内容:错误的初始假设,我将其保留为“记忆”]
date -R --utc && date -R --utc -d @$(date --utc +%s)
命令行解读:
第一个date
给出在我的电脑上设置的 UTC 日期;的$(date ...)
给出了Unix时间,即因为Unix纪元秒数减去所述(25这天)闰秒; date
如果没有正确管理闰秒,则使用此 Unix 时间作为参数应该给出过去 25 秒的日期,与第一个命令相比。事实并非如此,因此date
必须是“闰秒感知”。
我没有找到解决问题的简单方法,因此我编写了一个小 Bash 脚本来解决它。\xc2\xa0您需要下载下面链接中给出的闰秒文件并将其与脚本放在一起或更改它的路径。我还没写utc2unix.sh
,但是很容易适应。不要犹豫发表评论/提出建议......
unix2utc.sh:
\n\n#!/bin/bash\n\n# Convert a Unix timestamp to the real number of seconds\n# elapsed since the epoch.\n\n# Note: this script only manage additional leap seconds\n\n# Download leap-seconds.list from\n# https://github.com/eggert/tz/blob/master/leap-seconds.list\n\n# Get current timestamp if nothing is given as first param\nif [ -z $1 ]; then\n posix_time=$(date --utc +%s)\nelse\n posix_time=$1\nfi\n\n# Get the time at which leap seconds were added\nseconds_list=$(grep -v "^#" leap-seconds.list | cut -f 1 -d \' \')\n\n# Find the last leap second (see the content of leap-seconds.list)\n# 2208988800 seconds between 01-01-1900 and 01-01-1970:\nleap_seconds=$(echo $seconds_list | \\\n awk -v posix_time="$posix_time" \\\n \'{for (i=NF;i>0;i--)\n if (($i-2208988800) < posix_time) {\n print i-1; exit\n }\n } END {if (($(i+1)-2208988800) == posix_time) \n print "Warning: POSIX time ambiguity:",\n posix_time,\n "matches 2 values in UTC time!",\n "The smallest value is given." | "cat 1>&2"\n }\')\n# echo $leap_seconds\n\n# Add the leap seconds to the timestamp\nseconds_since_epoch=$(($posix_time + $leap_seconds))\n\necho $seconds_since_epoch\n
Run Code Online (Sandbox Code Playgroud)\n\n只是一些测试:
\n\ndate --utc +%s && ./unix2utc.sh
-> 从今天到 2015 年 6 月,差异为 25 秒。./unix2utc.sh 78796799
->78796799
./unix2utc.sh 78796801
->78796802
./unix2utc.sh 78796800
-> 78796800
+ 在标准错误上:Warning: POSIX time ambiguity: 78796800 matches 2 consecutive values in UTC time! Only the smallest value is given.