]> Cypherpunks repositories - gostls13.git/commitdiff
time: defer loading ZONEINFO until first time.LoadLocation call
authorJeff Johnson <jrjohnson@google.com>
Tue, 24 Jan 2017 19:45:20 +0000 (11:45 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 1 Feb 2017 21:12:31 +0000 (21:12 +0000)
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/35639
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/time/export_test.go
src/time/zoneinfo.go
src/time/zoneinfo_test.go

index 6cd535f6b197a76fdf55dd3d96c883451ae10459..38f2f45063cd8da926d5e2dec4025c1433b0402c 100644 (file)
@@ -18,6 +18,15 @@ func ForceUSPacificForTesting() {
        localOnce.Do(initTestingZone)
 }
 
+func ZoneinfoForTesting() *string {
+       return zoneinfo
+}
+
+func ResetZoneinfoForTesting() {
+       zoneinfo = nil
+       zoneinfoOnce = sync.Once{}
+}
+
 var (
        ForceZipFileForTesting = forceZipFileForTesting
        ParseTimeZone          = parseTimeZone
index fb0aa3924046fa853d18aca590e8878975fb958d..7cde142239cb1cdd5f8c00e16a7ae51fa77491ce 100644 (file)
@@ -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
 // 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.
 //
@@ -279,8 +280,12 @@ func LoadLocation(name string) (*Location, error) {
        if name == "Local" {
                return Local, nil
        }
-       if zoneinfo != "" {
-               if z, err := loadZoneFile(zoneinfo, name); err == nil {
+       zoneinfoOnce.Do(func() {
+               env, _ := syscall.Getenv("ZONEINFO")
+               zoneinfo = &env
+       })
+       if zoneinfo != nil && *zoneinfo != "" {
+               if z, err := loadZoneFile(*zoneinfo, name); err == nil {
                        z.name = name
                        return z, nil
                }
index 4b50dc509002f00877e67277dcd8331cc31170cc..e388e998d07d02cf09fe8c35dd9d67cf61901c75 100644 (file)
@@ -5,10 +5,36 @@
 package time_test
 
 import (
+       "fmt"
+       "os"
        "testing"
        "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) {
        time.ForceZipFileForTesting(true)
        defer time.ForceZipFileForTesting(false)