Home | History | Annotate | Download | only in time
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // +build darwin,386 darwin,amd64 dragonfly freebsd linux,!android nacl netbsd openbsd solaris
      6 
      7 // Parse "zoneinfo" time zone file.
      8 // This is a fairly standard file format used on OS X, Linux, BSD, Sun, and others.
      9 // See tzfile(5), http://en.wikipedia.org/wiki/Zoneinfo,
     10 // and ftp://munnari.oz.au/pub/oldtz/
     11 
     12 package time
     13 
     14 import (
     15 	"errors"
     16 	"runtime"
     17 	"syscall"
     18 )
     19 
     20 func initTestingZone() {
     21 	z, err := loadZoneFile(runtime.GOROOT()+"/lib/time/zoneinfo.zip", "America/Los_Angeles")
     22 	if err != nil {
     23 		panic("cannot load America/Los_Angeles for testing: " + err.Error())
     24 	}
     25 	z.name = "Local"
     26 	localLoc = *z
     27 }
     28 
     29 // Many systems use /usr/share/zoneinfo, Solaris 2 has
     30 // /usr/share/lib/zoneinfo, IRIX 6 has /usr/lib/locale/TZ.
     31 var zoneDirs = []string{
     32 	"/usr/share/zoneinfo/",
     33 	"/usr/share/lib/zoneinfo/",
     34 	"/usr/lib/locale/TZ/",
     35 	runtime.GOROOT() + "/lib/time/zoneinfo.zip",
     36 }
     37 
     38 var origZoneDirs = zoneDirs
     39 
     40 func forceZipFileForTesting(zipOnly bool) {
     41 	zoneDirs = make([]string, len(origZoneDirs))
     42 	copy(zoneDirs, origZoneDirs)
     43 	if zipOnly {
     44 		for i := 0; i < len(zoneDirs)-1; i++ {
     45 			zoneDirs[i] = "/XXXNOEXIST"
     46 		}
     47 	}
     48 }
     49 
     50 func initLocal() {
     51 	// consult $TZ to find the time zone to use.
     52 	// no $TZ means use the system default /etc/localtime.
     53 	// $TZ="" means use UTC.
     54 	// $TZ="foo" means use /usr/share/zoneinfo/foo.
     55 
     56 	tz, ok := syscall.Getenv("TZ")
     57 	switch {
     58 	case !ok:
     59 		z, err := loadZoneFile("", "/etc/localtime")
     60 		if err == nil {
     61 			localLoc = *z
     62 			localLoc.name = "Local"
     63 			return
     64 		}
     65 	case tz != "" && tz != "UTC":
     66 		if z, err := loadLocation(tz); err == nil {
     67 			localLoc = *z
     68 			return
     69 		}
     70 	}
     71 
     72 	// Fall back to UTC.
     73 	localLoc.name = "UTC"
     74 }
     75 
     76 func loadLocation(name string) (*Location, error) {
     77 	var firstErr error
     78 	for _, zoneDir := range zoneDirs {
     79 		if z, err := loadZoneFile(zoneDir, name); err == nil {
     80 			z.name = name
     81 			return z, nil
     82 		} else if firstErr == nil && !isNotExist(err) {
     83 			firstErr = err
     84 		}
     85 	}
     86 	if firstErr != nil {
     87 		return nil, firstErr
     88 	}
     89 	return nil, errors.New("unknown time zone " + name)
     90 }
     91