Commit 6d636064 authored by Jeff Johnson's avatar Jeff Johnson Committed by Brad Fitzpatrick

time: defer loading ZONEINFO until first time.LoadLocation call

A user application can now use os.Setenv("ZONEINFO", ..) becase the
value is no longer read on init of the time package.

Fixes #18619

Change-Id: Id8e303d67e6fb9c5d6ea9f969d8c94f6fff1bee3
Reviewed-on: https://go-review.googlesource.com/35639Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent ed8c62b7
...@@ -18,6 +18,15 @@ func ForceUSPacificForTesting() { ...@@ -18,6 +18,15 @@ func ForceUSPacificForTesting() {
localOnce.Do(initTestingZone) localOnce.Do(initTestingZone)
} }
func ZoneinfoForTesting() *string {
return zoneinfo
}
func ResetZoneinfoForTesting() {
zoneinfo = nil
zoneinfoOnce = sync.Once{}
}
var ( var (
ForceZipFileForTesting = forceZipFileForTesting ForceZipFileForTesting = forceZipFileForTesting
ParseTimeZone = parseTimeZone ParseTimeZone = parseTimeZone
......
...@@ -256,7 +256,8 @@ func (l *Location) lookupName(name string, unix int64) (offset int, isDST bool, ...@@ -256,7 +256,8 @@ func (l *Location) lookupName(name string, unix int64) (offset int, isDST bool,
// NOTE(rsc): Eventually we will need to accept the POSIX TZ environment // NOTE(rsc): Eventually we will need to accept the POSIX TZ environment
// syntax too, but I don't feel like implementing it today. // syntax too, but I don't feel like implementing it today.
var zoneinfo, _ = syscall.Getenv("ZONEINFO") var zoneinfo *string
var zoneinfoOnce sync.Once
// LoadLocation returns the Location with the given name. // LoadLocation returns the Location with the given name.
// //
...@@ -279,8 +280,12 @@ func LoadLocation(name string) (*Location, error) { ...@@ -279,8 +280,12 @@ func LoadLocation(name string) (*Location, error) {
if name == "Local" { if name == "Local" {
return Local, nil return Local, nil
} }
if zoneinfo != "" { zoneinfoOnce.Do(func() {
if z, err := loadZoneFile(zoneinfo, name); err == nil { env, _ := syscall.Getenv("ZONEINFO")
zoneinfo = &env
})
if zoneinfo != nil && *zoneinfo != "" {
if z, err := loadZoneFile(*zoneinfo, name); err == nil {
z.name = name z.name = name
return z, nil return z, nil
} }
......
...@@ -5,10 +5,36 @@ ...@@ -5,10 +5,36 @@
package time_test package time_test
import ( import (
"fmt"
"os"
"testing" "testing"
"time" "time"
) )
func init() {
if time.ZoneinfoForTesting() != nil {
panic(fmt.Errorf("zoneinfo initialized before first LoadLocation"))
}
}
func TestEnvVarUsage(t *testing.T) {
time.ResetZoneinfoForTesting()
testZoneinfo := "foo.zip"
env := "ZONEINFO"
defer os.Setenv(env, os.Getenv(env))
os.Setenv(env, testZoneinfo)
// Result isn't important, we're testing the side effect of this command
time.LoadLocation("Asia/Jerusalem")
defer time.ResetZoneinfoForTesting()
if zoneinfo := time.ZoneinfoForTesting(); testZoneinfo != *zoneinfo {
t.Errorf("zoneinfo does not match env variable: got %q want %q", zoneinfo, testZoneinfo)
}
}
func TestVersion3(t *testing.T) { func TestVersion3(t *testing.T) {
time.ForceZipFileForTesting(true) time.ForceZipFileForTesting(true)
defer time.ForceZipFileForTesting(false) defer time.ForceZipFileForTesting(false)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment