1 // Copyright 2011 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.
12 // A Location maps time instants to the zone in use at that time.
13 // Typically, the Location represents the collection of time offsets
14 // in use in a geographical area, such as CEST and CET for central Europe.
15 type Location struct {
20 // Most lookups will be for the current time.
21 // To avoid the binary search through tx, keep a
22 // static one-element cache that gives the correct
23 // zone for the time when the Location was created.
24 // if cacheStart <= t <= cacheEnd,
25 // lookup can return cacheZone.
26 // The units for cacheStart and cacheEnd are seconds
27 // since January 1, 1970 UTC, to match the argument
34 // A zone represents a single time zone such as CEST or CET.
36 name string // abbreviated name, "CET"
37 offset int // seconds east of UTC
38 isDST bool // is this zone Daylight Savings Time?
41 // A zoneTrans represents a single time zone transition.
42 type zoneTrans struct {
43 when int64 // transition time, in seconds since 1970 GMT
44 index uint8 // the index of the zone that goes into effect at that time
45 isstd, isutc bool // ignored - no idea what these mean
48 // UTC represents Universal Coordinated Time (UTC).
49 var UTC *Location = &utcLoc
51 // utcLoc is separate so that get can refer to &utcLoc
52 // and ensure that it never returns a nil *Location,
53 // even if a badly behaved client has changed UTC.
54 var utcLoc = Location{name: "UTC"}
56 // Local represents the system's local time zone.
57 var Local *Location = &localLoc
59 // localLoc is separate so that initLocal can initialize
60 // it even if a client has changed Local.
62 var localOnce sync.Once
64 func (l *Location) get() *Location {
69 localOnce.Do(initLocal)
74 // String returns a descriptive name for the time zone information,
75 // corresponding to the argument to LoadLocation.
76 func (l *Location) String() string {
80 // FixedZone returns a Location that always uses
81 // the given zone name and offset (seconds east of UTC).
82 func FixedZone(name string, offset int) *Location {
85 zone: []zone{{name, offset, false}},
86 tx: []zoneTrans{{-1 << 63, 0, false, false}},
90 l.cacheZone = &l.zone[0]
94 // lookup returns information about the time zone in use at an
95 // instant in time expressed as seconds since January 1, 1970 00:00:00 UTC.
97 // The returned information gives the name of the zone (such as "CET"),
98 // the start and end times bracketing sec when that zone is in effect,
99 // the offset in seconds east of UTC (such as -5*60*60), and whether
100 // the daylight savings is being observed at that time.
101 func (l *Location) lookup(sec int64) (name string, offset int, isDST bool, start, end int64) {
113 if zone := l.cacheZone; zone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
122 // Binary search for entry with largest time <= sec.
123 // Not using sort.Search to avoid dependencies.
136 zone := &l.zone[tx[0].index]
141 // end = maintained during the search
145 // lookupName returns information about the time zone with
146 // the given name (such as "EST").
147 func (l *Location) lookupName(name string) (offset int, isDST bool, ok bool) {
149 for i := range l.zone {
151 if zone.name == name {
152 return zone.offset, zone.isDST, true
158 // lookupOffset returns information about the time zone with
159 // the given offset (such as -5*60*60).
160 func (l *Location) lookupOffset(offset int) (name string, isDST bool, ok bool) {
162 for i := range l.zone {
164 if zone.offset == offset {
165 return zone.name, zone.isDST, true
171 // NOTE(rsc): Eventually we will need to accept the POSIX TZ environment
172 // syntax too, but I don't feel like implementing it today.
174 var zoneinfo, _ = syscall.Getenv("ZONEINFO")
176 // LoadLocation returns the Location with the given name.
178 // If the name is "" or "UTC", LoadLocation returns UTC.
179 // If the name is "Local", LoadLocation returns Local.
181 // Otherwise, the name is taken to be a location name corresponding to a file
182 // in the IANA Time Zone database, such as "America/New_York".
184 // The time zone database needed by LoadLocation may not be
185 // present on all systems, especially non-Unix systems.
186 // LoadLocation looks in the directory or uncompressed zip file
187 // named by the ZONEINFO environment variable, if any, then looks in
188 // known installation locations on Unix systems,
189 // and finally looks in $GOROOT/lib/time/zoneinfo.zip.
190 func LoadLocation(name string) (*Location, error) {
191 if name == "" || name == "UTC" {
198 if z, err := loadZoneFile(zoneinfo, name); err == nil {
203 return loadLocation(name)