Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(419)

Side by Side Diff: src/pkg/time/zoneinfo.go

Issue 5392041: code review 5392041: time: new Time, Duration, ZoneInfo types (Closed)
Patch Set: diff -r 3c286b9b2206 https://go.googlecode.com/hg/ Created 13 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/time/time_test.go ('k') | src/pkg/time/zoneinfo_plan9.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 The Go Authors. All rights reserved. 1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // +build darwin freebsd linux openbsd plan9
6
7 package time 5 package time
8 6
9 import "sync" 7 import "sync"
10 8
11 // Parsed representation 9 // A Location maps time instants to the zone in use at that time.
12 type zone struct { 10 // Typically, the Location represents the collection of time offsets
13 » utcoff int 11 // in use in a geographical area, such as CEST and CET for central Europe.
14 » isdst bool 12 type Location struct {
15 » name string 13 » name string
14 » zone []zone
15 » tx []zoneTrans
16
17 » // Most lookups will be for the current time.
18 » // To avoid the binary search through tx, keep a
19 » // static one-element cache that gives the correct
20 » // zone for the time when the Location was created.
21 » // if cacheStart <= t <= cacheEnd,
22 » // lookup can return cacheZone.
23 » // The units for cacheStart and cacheEnd are seconds
24 » // since January 1, 1970 UTC, to match the argument
25 » // to lookup.
26 » cacheStart int64
27 » cacheEnd int64
28 » cacheZone *zone
16 } 29 }
17 30
18 type zonetime struct { 31 // A zone represents a single time zone such as CEST or CET.
19 » time int32 // transition time, in seconds since 1970 GMT 32 type zone struct {
20 » zone *zone // the zone that goes into effect at that time 33 » name string // abbreviated name, "CET"
34 » offset int // seconds east of UTC
35 » isDST bool // is this zone Daylight Savings Time?
36 }
37
38 // A zoneTrans represents a single time zone transition.
39 type zoneTrans struct {
40 » when int64 // transition time, in seconds since 1970 GMT
41 » index uint8 // the index of the zone that goes into effect at tha t time
21 isstd, isutc bool // ignored - no idea what these mean 42 isstd, isutc bool // ignored - no idea what these mean
22 } 43 }
23 44
24 var zones []zonetime 45 // UTC represents Universal Coordinated Time (UTC).
25 var onceSetupZone sync.Once 46 var UTC *Location = &utcLoc
26 47
27 // Look up the correct time zone (daylight savings or not) for the given unix ti me, in the current location. 48 // utcLoc is separate so that get can refer to &utcLoc
28 func lookupTimezone(sec int64) (zone string, offset int) { 49 // and ensure that it never returns a nil *Location,
29 » onceSetupZone.Do(setupZone) 50 // even if a badly behaved client has changed UTC.
30 » if len(zones) == 0 { 51 var utcLoc = Location{name: "UTC"}
31 » » return "UTC", 0 52
53 // Local represents the system's local time zone.
54 var Local *Location = &localLoc
55
56 // localLoc is separate so that initLocal can initialize
57 // it even if a client has changed Local.
58 var localLoc Location
59 var localOnce sync.Once
60
61 func (l *Location) get() *Location {
62 » if l == nil {
63 » » return &utcLoc
64 » }
65 » if l == &localLoc {
66 » » localOnce.Do(initLocal)
67 » }
68 » return l
69 }
70
71 // String returns a descriptive name for the time zone information,
72 // corresponding to the argument to LoadLocation.
73 func (l *Location) String() string {
74 » return l.get().name
75 }
76
77 // FixedZone returns a Location that always uses
78 // the given zone name and offset (seconds east of UTC).
79 func FixedZone(name string, offset int) *Location {
80 » l := &Location{
81 » » name: name,
82 » » zone: []zone{{name, offset, false}},
83 » » tx: []zoneTrans{{-1 << 63, 0, false, false}},
84 » » cacheStart: -1 << 63,
85 » » cacheEnd: 1<<63 - 1,
86 » }
87 » l.cacheZone = &l.zone[0]
88 » return l
89 }
90
91 // lookup returns information about the time zone in use at an
92 // instant in time expressed as seconds since January 1, 1970 00:00:00 UTC.
93 //
94 // The returned information gives the name of the zone (such as "CET"),
95 // the start and end times bracketing sec when that zone is in effect,
96 // the offset in seconds east of UTC (such as -5*60*60), and whether
97 // the daylight savings is being observed at that time.
98 func (l *Location) lookup(sec int64) (name string, offset int, isDST bool, start , end int64) {
99 » l = l.get()
100
101 » if len(l.tx) == 0 {
102 » » name = "UTC"
103 » » offset = 0
104 » » isDST = false
105 » » start = -1 << 63
106 » » end = 1<<63 - 1
107 » » return
32 } 108 }
33 109
34 » // Binary search for entry with largest time <= sec 110 » if zone := l.cacheZone; zone != nil && l.cacheStart <= sec && sec < l.ca cheEnd {
35 » tz := zones 111 » » name = zone.name
36 » for len(tz) > 1 { 112 » » offset = zone.offset
37 » » m := len(tz) / 2 113 » » isDST = zone.isDST
38 » » if sec < int64(tz[m].time) { 114 » » start = l.cacheStart
39 » » » tz = tz[0:m] 115 » » end = l.cacheEnd
116 » » return
117 » }
118
119 » // Binary search for entry with largest time <= sec.
120 » // Not using sort.Search to avoid dependencies.
121 » tx := l.tx
122 » end = 1<<63 - 1
123 » for len(tx) > 1 {
124 » » m := len(tx) / 2
125 » » lim := tx[m].when
126 » » if sec < lim {
127 » » » end = lim
128 » » » tx = tx[0:m]
40 } else { 129 } else {
41 » » » tz = tz[m:] 130 » » » tx = tx[m:]
42 } 131 }
43 } 132 }
44 » z := tz[0].zone 133 » zone := &l.zone[tx[0].index]
45 » return z.name, z.utcoff 134 » name = zone.name
135 » offset = zone.offset
136 » isDST = zone.isDST
137 » start = tx[0].when
138 » // end = maintained during the search
139 » return
46 } 140 }
47 141
48 // lookupByName returns the time offset for the 142 // lookupName returns information about the time zone with
49 // time zone with the given abbreviation. It only considers 143 // the given name (such as "EST").
50 // time zones that apply to the current system. 144 func (l *Location) lookupName(name string) (offset int, isDST bool, ok bool) {
51 // For example, for a system configured as being in New York, 145 » l = l.get()
52 // it only recognizes "EST" and "EDT". 146 » for i := range l.zone {
53 // For a system in San Francisco, "PST" and "PDT". 147 » » zone := &l.zone[i]
54 // For a system in Sydney, "EST" and "EDT", though they have 148 » » if zone.name == name {
55 // different meanings than they do in New York. 149 » » » return zone.offset, zone.isDST, true
56 func lookupByName(name string) (off int, found bool) {
57 » onceSetupZone.Do(setupZone)
58 » for _, z := range zones {
59 » » if name == z.zone.name {
60 » » » return z.zone.utcoff, true
61 } 150 }
62 } 151 }
63 » return 0, false 152 » return
64 } 153 }
154
155 // lookupOffset returns information about the time zone with
156 // the given offset (such as -5*60*60).
157 func (l *Location) lookupOffset(offset int) (name string, isDST bool, ok bool) {
158 l = l.get()
159 for i := range l.zone {
160 zone := &l.zone[i]
161 if zone.offset == offset {
162 return zone.name, zone.isDST, true
163 }
164 }
165 return
166 }
167
168 // NOTE(rsc): Eventually we will need to accept the POSIX TZ environment
169 // syntax too, but I don't feel like implementing it today.
170
171 // NOTE(rsc): Using the IANA names below means ensuring we have access
172 // to the database. Probably we will ship the files in $GOROOT/lib/zoneinfo/
173 // and only look there if there are no system files available (such as on Window s).
174 // The files total 200 kB.
175
176 // LoadLocation returns the Location with the given name.
177 //
178 // If the name is "" or "UTC", LoadLocation returns UTC.
179 // If the name is "Local", LoadLocation returns Local.
180 //
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".
183 func LoadLocation(name string) (*Location, error) {
184 if name == "" || name == "UTC" {
185 return UTC, nil
186 }
187 if name == "Local" {
188 return Local, nil
189 }
190 return loadLocation(name)
191 }
OLDNEW
« no previous file with comments | « src/pkg/time/time_test.go ('k') | src/pkg/time/zoneinfo_plan9.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b