Go 中的时间表示长度



在Unix下,我正在开发一个程序,该程序需要根据时间是32位(将包装在2038位)还是64位而有所不同。

我认为围棋时间并不神奇,它将在 2038 年包装在一个具有 32 位time_t的平台上。 如果这是错误的,并且它以某种方式总是 64 位,请告诉我,因为这将防止很多悲伤。

在 Go 中为平台的time_t大小编写测试的最简单方法是什么? 还有什么比cgo的明显黑客更简单的方法吗?

如果真的想找到time_t的大小,可以用cgo链接到time.h。然后,time_t的大小将作为C.sizeof_time_t提供。它并没有变得简单得多。

package main
// #include <time.h>
import "C"
import (
"fmt"
)
func main() {
fmt.Println(C.sizeof_time_t);
}

除了尝试将系统时间设置为越来越远的日期(这对该系统上运行的任何其他内容都不是很礼貌)之外,我不知道有什么方法可以在任何编程语言中以可移植的方式直接查询硬件时钟的限制。C 只是在操作系统提供的文件中硬编码time_t的大小(在 OS X 上是/usr/include/i386/_types.h),因此您最好通过cgo查询time_t的大小来利用这些信息。

但是这样做的理由很少。Go 不使用time_t,并且似乎不会遇到 2038 问题,除非您实际计划在 2038 年在 32 位机器上运行代码。如果这是你的计划,我建议找一个更好的计划。


我认为围棋时间并不神奇,它将在 2038 年包装在一个具有 32 位time_t的平台上。如果这是错误的,并且它以某种方式总是 64 位,请告诉我,因为这将防止很多悲伤。

2038 年问题的大部分内容是假设自 1970 年以来的时间适合 32 位有符号整数的程序。这会影响时间和日期函数,以及自 1970 年以来选择将时间表示为 32 位有符号整数的网络和数据格式。这不是一些硬件限制(除非它实际上是 2038 年,见下文),而是旧编程语言和协议的设计限制。没有什么能阻止您使用 64 位整数来表示时间,或选择不同的纪元。这正是较新的编程语言所做的,不需要魔法。

Go 于 2009 年首次发布,此前 Unicode、并发性和 32 位时间(即 2038 年问题)等问题被认为是任何编程语言都必须解决的问题。考虑到 C 的时间库存在多少问题,我非常怀疑 Go 是否正在使用它。快速浏览源代码即可确认。


虽然我在 Go 文档中找不到任何明确提及其Time表示的限制,但它似乎与 C 的time.h结构(如time_t)完全脱节。由于Time使用64位整数,因此除非您要求实际时钟时间,否则似乎可以清除2038问题。

深入研究 Go 文档Time我们发现它们的 0 远远超出了 32 位time_t的范围,范围从 1901 年到 2038 年。

时间类型的零值是第 1 年 1 月 1 日 00:00:00.000000000 UTC

time.Unix需要秒和纳秒作为 64 位整数,毫无疑问它与time_t的大小分离。

time.Parse将解析">在 0000..9999 范围内"的一年,再次远远超出 32 位time_t的范围。

等等。我能找到的唯一限制是持续时间限制为 290 年,因为它具有纳秒精度,而 290 年约为 63 位纳秒。

当然,您应该在具有 32 位time_t的机器上测试您的代码。


2038年问题的一个侧面问题是时区。计算机从时区数据库(通常是 IANA 时区数据库)计算时区信息。这允许人们在特定时间获取特定位置的时间偏移量。

计算机安装了自己的时区数据库副本。不幸的是,很难知道它们的位置或上次更新的时间。为了避免此问题,大多数编程语言都提供了自己的时区数据库副本。围棋也是如此。


具有 32 位时间的机器上唯一真正的限制是其硬件时钟的限制。这告诉软件现在是什么时间。只有当您的程序在 2038 年仍在 32 位机器上运行时,32 位时钟才会成为问题。缓解这一点没有多大意义,因为该机器上的所有内容都会遇到相同的问题,而且他们不太可能考虑到这一点。您最好在 2038 年之前停用该硬件。

通常,time.Time使用 63 位来表示自第 1 年 1 月 1 日 00:00:00 UTC 以来一直到 219250468-12-04 15:30:09.147483647 +0000 UTC 以来经过的挂钟秒数。例如

package main
import (
"fmt"
"time"
)
func main() {
var t time.Time
fmt.Println(t)
t = time.Unix(1<<63-1, 1<<31-1)
fmt.Println(t)
}

游乐场:https://play.golang.org/p/QPs1m6eMPH

输出:

0001-01-01 00:00:00 +0000 UTC
219250468-12-04 15:30:09.147483647 +0000 UTC

如果time.Time是单调的(派生自time.Now()),time.Time使用33位来表示挂钟秒,涵盖1885年至2157年。

引用:

打包时间

建议:围棋中的单调经过时间测量

最新更新