在Go语言中,最大的time.Time是多少?

23

我正在寻找关于Go语言中最大时间(Max time.Time)的文档。

其他编程语言会明确指出,例如C#:http://msdn.microsoft.com/en-us/library/system.datetime.maxvalue(v=vs.110).aspx

public static readonly DateTime MaxValue

这个常量的值相当于公元10000年1月1日00:00:00的前一100纳秒滴答,即9999年12月31日23:59:59.9999999。在Go中,time.Time的最大值是多少?有没有相关文档说明?

time.Time由int64支持:http://golang.org/src/pkg/time/time.go#L34 - Martin Gallagher
3个回答

38
在Go语言中,time.Time被存储为一个int64加上一个32位的纳秒值。但是,如果你使用@JimB的答案,你将会触发sec组件上的整数溢出,导致像time.Before()这样的比较无法工作。
这是因为time.Unix(sec, nsec)会向sec添加一个偏移量,该偏移量表示从公元1年(Go中的零时间)到1970年(Unix中的零时间)之间的秒数。
@twotwotwo的playground示例在http://play.golang.org/p/i6S_T4-X3v中很清楚地说明了这一点,但这里是一个简化版本。
// number of seconds between Year 1 and 1970 (62135596800 seconds)
unixToInternal := int64((1969*365 + 1969/4 - 1969/100 + 1969/400) * 24 * 60 * 60)

// max1 gets time.Time struct: {-9223371974719179009 999999999}
max1 := time.Unix(1<<63-1, 999999999)
// max2 gets time.Time struct: {9223372036854775807 999999999}
max2 := time.Unix(1<<63-1-unixToInternal, 999999999)

// t0 is definitely before the year 292277026596
t0 := time.Date(2015, 9, 16, 19, 17, 23, 0, time.UTC)

// t0 < max1 doesn't work: prints false
fmt.Println(t0.Before(max1))
// max1 < t0 doesn't work: prints true
fmt.Println(t0.After(max1))
fmt.Println(max1.Before(t0))

// t0 < max2 works: prints true
fmt.Println(t0.Before(max2))
// max2 < t0 works: prints false
fmt.Println(t0.After(max2))
fmt.Println(max2.Before(t0))

因此,尽管有点麻烦,如果您想要一个适用于比较的最大time.Time值,比如查找一系列时间中的最小值,您可以使用time.Unix(1<<63-62135596801, 999999999)


26

在 Go 语言中,时间被存储为 int64 类型加上一个 32 位的纳秒值(目前是 uintptr 类型,出于技术原因),因此不必担心时间会耗尽。

t := time.Unix(1<<63-1, 0)
fmt.Println(t.UTC())

打印 219250468-12-04 15:30:07 +0000 UTC

如果出于某些原因您需要一个有用的最大时间(有关详细信息,请参见@cce's answer),您可以使用:

maxTime := time.Unix(1<<63-62135596801, 999999999)

1
哈哈,知道了真棒。没有问题! - twotwotwo
2
@twotwotwo 实际上,它发生在“292277026596-12-04 15:30:07.999999999 +0000 UTC”之前 - 请查看http://play.golang.org/p/O8A2QhQLka - Momer
2
@Momer 啊,太激动人心了!根据你的示例进行调整后,似乎我需要在我的日历上为 219248499-12-06 15:30:07.999999999 进行预约(通过从秒数中减去 unixToInternal 来使与 1970 年的比较正确:http://play.golang.org/p/i6S_T4-X3v)。每天都会学到新东西! - twotwotwo
如果你将要进行 .Before / .After 比较,请务必查看 cce 的答案。 - Kyle Brandt
@KyleBrandt:哦,谢谢提醒,我忘记很久以前就该修复这个问题了。 - JimB
显示剩余2条评论

4
请注意,尽管 @cce 的答案确保了 AfterBefore 的工作,但其他 API 不会。 UnixNano 仅在1970年左右的±292年范围内工作(1678年至2262年之间)。此外,由于最长持续时间约为292年,即使是这两个函数在Sub上也会给出一个被钳制的结果。
因此,一种替代方案是选择一个最小值[1]并执行以下操作:
var MinTime = time.Unix(-2208988800, 0) // Jan 1, 1900
var MaxTime = MinTime.Add(1<<63 - 1)

在这些情况下,所有内容应该都正常工作。

[1]: 如果您不关心1970年之前的日期,则另一个明显的选择是time.Unix(0, 0)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接