我刚刚发现 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:01!!如果您认为(正如我之前所做的那样)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
必须具有“闰秒意识”。
答案1
我没有找到解决问题的简单方法,因此我编写了一个小型 Bash 脚本来解决它。您需要下载下面链接中给出的闰秒文件并将其与脚本放在一起或更改其路径。我还没写utc2unix.sh
,但是很容易适应。不要犹豫发表评论/提出建议......
unix2utc.sh:
#!/bin/bash
# Convert a Unix timestamp to the real number of seconds
# elapsed since the epoch.
# Note: this script only manage additional leap seconds
# Download leap-seconds.list from
# https://github.com/eggert/tz/blob/master/leap-seconds.list
# Get current timestamp if nothing is given as first param
if [ -z $1 ]; then
posix_time=$(date --utc +%s)
else
posix_time=$1
fi
# Get the time at which leap seconds were added
seconds_list=$(grep -v "^#" leap-seconds.list | cut -f 1 -d ' ')
# Find the last leap second (see the content of leap-seconds.list)
# 2208988800 seconds between 01-01-1900 and 01-01-1970:
leap_seconds=$(echo $seconds_list | \
awk -v posix_time="$posix_time" \
'{for (i=NF;i>0;i--)
if (($i-2208988800) < posix_time) {
print i-1; exit
}
} END {if (($(i+1)-2208988800) == posix_time)
print "Warning: POSIX time ambiguity:",
posix_time,
"matches 2 values in UTC time!",
"The smallest value is given." | "cat 1>&2"
}')
# echo $leap_seconds
# Add the leap seconds to the timestamp
seconds_since_epoch=$(($posix_time + $leap_seconds))
echo $seconds_since_epoch
只是一些测试:
date --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.