在Go语言中,`time.Time`的最大值是`9999-12-31 23:59:59.999999999 +0000 UTC`。

huangapple go评论71阅读模式
英文:

What is the maximum time.Time in Go?

问题

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

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

public static readonly DateTime MaxValue

此常量的值相当于9999年12月31日23:59:59.9999999,即在10000年1月1日00:00:00之前的100纳秒刻度。

Go语言中的最大time.Time是多少?有没有相关的文档记录?

英文:

I'm looking for documentation on the Max time.Time in go.

Other languages make it explicit, for example in C#: http://msdn.microsoft.com/en-us/library/system.datetime.maxvalue(v=vs.110).aspx

public static readonly DateTime MaxValue

> The value of this constant is equivalent to 23:59:59.9999999, December
> 31, 9999, exactly one 100-nanosecond tick before 00:00:00, January 1,
> 10000.

What is the maximum time.Time in Go? Is it documented somewhere?

答案1

得分: 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中清楚地说明了这一点,但这里是一个简化版本。

// 公元1年到1970年之间的秒数(62135596800秒)
unixToInternal := int64((1969*365 + 1969/4 - 1969/100 + 1969/400) * 24 * 60 * 60)

// max1 获取 time.Time 结构体:{-9223371974719179009 999999999}
max1 := time.Unix(1<<63-1, 999999999)
// max2 获取 time.Time 结构体:{9223372036854775807 999999999}
max2 := time.Unix(1<<63-1-unixToInternal, 999999999)

// t0 显然在公元292277026596年之前
t0 := time.Date(2015, 9, 16, 19, 17, 23, 0, time.UTC)

// t0 < max1 不起作用:输出 false
fmt.Println(t0.Before(max1))
// max1 < t0 不起作用:输出 true
fmt.Println(t0.After(max1))
fmt.Println(max1.Before(t0))

// t0 < max2 起作用:输出 true
fmt.Println(t0.Before(max2))
// max2 < t0 起作用:输出 false
fmt.Println(t0.After(max2))
fmt.Println(max2.Before(t0))

因此,虽然有点麻烦,但如果你想要一个用于比较的最大time.Time,你可以使用time.Unix(1<<63-62135596801, 999999999)。这对于在一系列时间中找到最小值的比较是有用的。

英文:

time.Time in go is stored as an int64 plus a 32-bit nanosecond value, but if you use @JimB's answer you will trigger an integer overflow on the sec component and comparisons like time.Before() will not work.

This is because time.Unix(sec, nsec) adds an offset of 62135596800 seconds to sec that represents the number of seconds between the year 1 (zero time in Go) and 1970 (zero time in Unix).

@twotwotwo's playground example makes this clear in http://play.golang.org/p/i6S_T4-X3v but here is a distilled version.

// 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&lt;&lt;63-1, 999999999)
// max2 gets time.Time struct: {9223372036854775807 999999999}
max2 := time.Unix(1&lt;&lt;63-1-unixToInternal, 999999999)

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

// t0 &lt; max1 doesn&#39;t work: prints false
fmt.Println(t0.Before(max1))
// max1 &lt; t0 doesn&#39;t work: prints true
fmt.Println(t0.After(max1))
fmt.Println(max1.Before(t0))

// t0 &lt; max2 works: prints true
fmt.Println(t0.Before(max2))
// max2 &lt; t0 works: prints false
fmt.Println(t0.After(max2))
fmt.Println(max2.Before(t0))

So while it is a bit of a pain you can use time.Unix(1&lt;&lt;63-62135596801, 999999999) if you want a max time.Time that is useful for comparisons like finding the minimum value in a range of times.

答案2

得分: 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的回答),你可以使用:

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

Time in go is stored as an int64 plus a 32bit Nanosec value (currently a uintptr for technical reasons), so there's no real worry about running out.

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

prints 219250468-12-04 15:30:07 +0000 UTC

If for some reason you want a useful max time (see @cce's answer for details), you can use:

maxTime := time.Unix(1&lt;&lt;63-62135596801, 999999999)

答案3

得分: 4

请注意,尽管@cce的答案确保AfterBefore会起作用,但其他API可能不会。UnixNano只在1970年前后的大约±292年范围内有效(在1678年和2262年之间)。此外,由于最大持续时间约为292年,即使使用这两个函数的结果也会被截断。

因此,一个替代方案是选择一个最小值<sup>[1]</sup>并执行以下操作:

var MinTime = time.Unix(-2208988800, 0) // 1900年1月1日
var MaxTime = MinTime.Add(1&lt;&lt;63 - 1)

在这个范围内,一切都应该正常工作。

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

英文:

Note that, although @cce's answer ensures After and Before will work, other APIs won't. UnixNano only works within ±292 years around 1970 (between 1678 and 2262). Also, since maximum duration is ~292 years, even those two will give a clamped result on Sub.

So, an alternative is to pick a minimum<sup>[1]</sup> value and do:

var MinTime = time.Unix(-2208988800, 0) // Jan 1, 1900
var MaxTime = MinTime.Add(1&lt;&lt;63 - 1)

Within these, everything should work.

[1]: An other obvious choice is time.Unix(0, 0) if you don't care about dates before 1970.

huangapple
  • 本文由 发表于 2014年8月1日 01:11:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/25065055.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定