- 时区 = CEST
- 日期(GNU coreutils)8.32
date -d "115 years ago"
Di 11. Aug 13:37:54 CET 1908
date -d "116 years ago"
date: invalid date ‘116 years ago’
问题
- 是否有可能返回
115 years
更多过去的或5879565 years
进入未来? - 为什么会发生这种情况并引发错误?这些奇数从何而来?
- 为什么
date -d "200 years ago 14 Mar "
突然就可以工作了呢?
答案1
有许多几乎兼容的计算时间和日期的方法。
“传统”unix 时间从 1970 年(又名“纪元”)开始计算秒数。这有一个大问题在 32 位表示中,它将在 2038 年 1 月 19 日星期二 ( ) 遇到整数溢出date -d "@$((0x7fffffff))"
。
更“现代”的方法是在 64 位计数器中计算纳秒。
GNU coreutils 'date' 将日期解析委托给解析日期时间2.y,这是 2500 行 bison 代码。该行为还取决于环境。例如,使用 coreutils 8.32,我在 Cygwin 和 Ubuntu 下得到不同的行为,即使它们都是从相同的源编译的。我还在coreutils 8.22
64 位 CentOS7 上运行,它接受从“20000000000 年前”到“20000000000 年”的日期
总之 - 这取决于您的实施date
。
编辑添加:
菲利普·库林(Philip Couling)有一些发现。时区很难正确处理。
另外,请阅读程序员对时间的误解。时间似乎是一个简单的话题,但要正确处理它却很困难。
答案2
我强烈怀疑这里的最小限制115 years ago
(1908)是由您的时区引起的。但由于您没有提到您所在的时区,我无法确定。
大多数计算机系统要么设置为 UTC,要么设置为指定的地理时区,通常引用城市,例如Europe/London
。地理时区考虑到政府改变一个地方的时区并要求数据库特定地点的时区从具体日期/时间。这允许日期/时间在夏令时变化和大多数政治愚蠢行为中发挥作用。
因此,最有可能的情况是,您所在的时区仅记录了 1908 年左右的时区偏移量。另一方面,UTC 计算将无限期地回溯,因为时区数据库使用 UTC(以及 1960 年之前的 UT [GMT])作为参考时间。
时区的概念确实令人惊讶地新颖,第一次同步发生在1840年。在此之前的任何时区计算都将是混乱的猜测,并且可能涉及大陆漂移的调整。
未来 5879565 年的计算很可能是系统性的,并且与 Unix 时间相关(自 1970 年 1 月 1 日 GMT 以来的秒数,不考虑 UTC 闰秒)。
但也应该小心相信未来的计算。您不知道 100 年后某个地区的时区是什么。而且该代码当然没有考虑到 580 万年来相对于格林威治的巨大漂移。
答案3
这实际上取决于您正在使用的实现:
在我的版本中,没有这样的限制:
$ date -d "120 years ago"
Wed 12 Aug 14:20:26 UTC 1903
$ date -d "5000 years ago"
Tue 12 Aug 14:21:26 UTC -2977
(当然,对于如此早的日期,所使用的预产历必须持保留态度)
$ date -d "+9879566 years"
Sat 12 Aug 14:24:17 UTC 9881589
$ date -d "+1000000000 years"
Sat 12 Aug 14:23:39 UTC 1000002023
它让我可以上下移动超过 200 万年:
$ date -d "+2147483524 years"
Tue 12 Aug 14:29:19 UTC 2147485547
$ date -d "+2147483525 years"
date: invalid date '+2147483525 years'
(124 年小于 2³1 = 2147483648)
$ date -d "2147483772 years ago"
date: invalid date '2147483772 years ago'
$ date -d "2147483771 years ago"
Thu 12 Aug 14:32:23 UTC -2147481748
(123 年小于 2³1 = 2147483648)
struct tm
这表明在最初计算要添加或减去的年数时,它在内部使用 a 的 tm_year (从 1900 年开始)上的 32 位有符号值。
答案4
使用日期 --version = 8.32:-
date -d "116 years ago"
给出日期:无效日期“116 年前”
但强制它以 UTC 显示date -ud "116 years ago"
给出 Tue 13 Aug 12:13:25 UTC 1907
事实上:-
date -ud "20240000 years ago"
产生 Sun 13 Aug 12:15:55 UTC -20237977