Reputation: 117
Under Unix, I'm working on a program that needs to behave differently depending on whether time is 32-bit (will wrap in 2038) or 64-bit.
I presume Go time is not magic and will wrap in 2038 on a platform with a 32-bit time_t. If this is false and it is somehow always 64-bit, clue me in because that will prevent much grief.
What's the simplest way in Go to write a test for the platform's time_t size? Is there any way simpler than the obvious hack with cgo?
Upvotes: 3
Views: 2134
Reputation: 164629
If you really want to find the size of time_t
, you can use cgo
to link to time.h
. Then the sizeof time_t
will be available as C.sizeof_time_t
. It doesn't get much simpler.
package main
// #include <time.h>
import "C"
import (
"fmt"
)
func main() {
fmt.Println(C.sizeof_time_t);
}
Other than trying to set the system time to increasingly distant dates, which is not very polite to anything else running on that system, I don't know of any way to directly query the limits of the hardware clock in a portable fashion in any programming language. C simply hard codes the size of time_t
in a file provided by the operating system (on OS X it's /usr/include/i386/_types.h
), so you're probably best off taking advantage of that information by querying the size of time_t
via cgo
.
But there's very few reasons to do this. Go does not use time_t
and does not appear to suffer from 2038 issues unless you actually plan to have code running on a 32-bit machine in 2038. If that's your plan, I'd suggest finding a better plan.
I presume Go time is not magic and will wrap in 2038 on a platform with a 32-bit time_t. If this is false and it is somehow always 64-bit, clue me in because that will prevent much grief.
Most of the the Year 2038 Problem is programs assuming that the time since 1970 will fit in a 32-bit signed integer. This effects time and date functions, as well as network and data formats which choose to represent time as a 32-bit signed integer since 1970. This is not some hardware limit (except if it's actually 2038, see below), but rather a design limitation of older programming languages and protocols. There's nothing stopping you from using 64 bit integers to represent time, or choosing a different epoch. And that's exactly what newer programming languages do, no magic required.
Go was first released in 2009 long after issues such as Unicode, concurrency, and 32-bit time (ie. the Year 2038 Problem) were acknowledged as issues any programming language would have to tackle. Given how many issues there are with C's time library, I highly doubt that Go is using it at all. A quick skim of the source code confirms.
While I can't find any explicit mention in the Go documentation of the limits of its Time
representation, it appears to be completely disconnected from C's time.h
structures such as time_t
. Since Time
uses 64 bit integers, it seems to be clear of 2038 problems unless you're asking for actual clock time.
Digging into the Go docs for Time
we find their 0 is well outside the range of a 32-bit time_t
which ranges from 1901 to 2038.
The zero value of type Time is January 1, year 1, 00:00:00.000000000 UTC
time.Unix
takes seconds and nanoseconds as 64 bit integers leaving no doubt that it is divorced from the size of time_t
.
time.Parse
will parse a year "in the range 0000..9999", again well outside the range of a 32-bit time_t
.
And so on. The only limitation I could find is that a Duration is limited to 290 years because it has a nanosecond accuracy and 290 years is about 63 bits worth of nanoseconds.
Of course, you should test your code on a machine with a 32-bit time_t
.
One side issue of the 2038 Problem is time zones. Computers calculate time zone information from a time zone database, usually the IANA time zone database. This allows one to get the time offset for a certain location at a certain time.
Computers have their own copy of the time zone database installed. Unfortunately its difficult to know where they are located or when they were last updated. To avoid this issue, most programming languages supply their own copy of the time zone database. Go does as well.
The only real limitation on a machine with 32-bit time is the limits of its hardware clock. This tells the software what time it is right now. A 32-bit clock only becomes an issue if your program is still running on a 32-bit machine in 2038. There isn't much point to mitigating that because everything on that machine will have the same problem and its unlikely they took it into account. You're better off decommissioning that hardware before 2038.
Upvotes: 3
Reputation: 166529
Ordinarily, time.Time
uses 63 bits to represent wall clock seconds elapsed since January 1, year 1 00:00:00 UTC, up through 219250468-12-04 15:30:09.147483647 +0000 UTC. For example,
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)
}
Playground: https://play.golang.org/p/QPs1m6eMPH
Output:
0001-01-01 00:00:00 +0000 UTC
219250468-12-04 15:30:09.147483647 +0000 UTC
If time.Time
is monotonic (derived from time.Now()
), time.Time
uses 33 bits to represent wall clock seconds, covering the years 1885 through 2157.
References:
Proposal: Monotonic Elapsed Time Measurements in Go
Upvotes: 1