Go中的时间长度表示

时间:2017-12-04 21:35:47

标签: go time

在Unix下,我正在开发一个程序,需要根据时间是32位(将在2038中换行)还是64位来表现不同。

我认为Go time不是魔术,并且将在2038年在具有32位time_t的平台上包装。如果这是假的,并且它总是64位,请提示我,因为这样可以避免很多悲伤。

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

2 个答案:

答案 0 :(得分:3)

如果您确实想要找到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),所以你可能最好通过查询{的大小来利用这些信息。 {1}}通过time_t

但这样做的理由很少。 Go不使用cgo并且似​​乎没有遭遇2038问题,除非您实际计划在2038年在32位计算机上运行代码。如果这是您的计划,我建议您找一个更好的计划。< / p>

  

我认为Go time不是魔术,并且将在2038年在具有32位time_t的平台上进行包装。如果这是假的,并且它总是64位,请提示我,因为这样可以避免很多悲伤。

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

在Java,并发和32位时间(即Year 2038 Problem)等问题被认为是任何编程语言必须解决的问题之后很久,Go才在2009年首次发布。考虑到C的时间库存在多少问题,我非常怀疑Go是否正在使用它。 A quick skim of the source code confirms

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

深入研究the Go docs for Time我们发现他们的0远远超出了32位Time的范围,范围从1901年到2038年。

  

Time类型的零值是1月1日,第1年00:00:00.0000000000 UTC

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

time.Parse将解析一年“在0000..9999 范围内”,同样远远超出32位time_t的范围。

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

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

2038问题的一个侧面问题是时区。计算机从时区数据库计算时区信息,通常为the IANA time zone database。这允许人们在特定时间获得某个位置的时间偏移。

计算机拥有自己的时区数据库副本。不幸的是,很难知道它们的位置或最后更新的时间。为避免此问题,大多数编程语言都提供自己的时区数据库副本。 Go does as well

32位时间机器的唯一真正限制是其硬件时钟的限制。这告诉软件现在的时间。如果您的程序在2038年仍然在32位计算机上运行,​​那么32位时钟只会成为问题。由于 所有 ,因此没有太大的意义那台机器会遇到同样的问题而且不太可能将它考虑在内。你最好在2038年之前停止使用该硬件。

答案 1 :(得分:1)

通常,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年。

参考文献:

Package time

Proposal: Monotonic Elapsed Time Measurements in Go