Source file
src/time/zoneinfo_windows.go
1
2
3
4
5 package time
6
7 import (
8 "errors"
9 "internal/syscall/windows/registry"
10 "syscall"
11 )
12
13 var platformZoneSources []string
14
15
16
17
18
19
20
21
22
23
24
25 func matchZoneKey(zones registry.Key, kname string, stdname, dstname string) (matched bool, err2 error) {
26 k, err := registry.OpenKey(zones, kname, registry.READ)
27 if err != nil {
28 return false, err
29 }
30 defer k.Close()
31
32 var std, dlt string
33 if err = registry.LoadRegLoadMUIString(); err == nil {
34
35 std, err = k.GetMUIStringValue("MUI_Std")
36 if err == nil {
37 dlt, err = k.GetMUIStringValue("MUI_Dlt")
38 }
39 }
40 if err != nil {
41 if std, _, err = k.GetStringValue("Std"); err != nil {
42 return false, err
43 }
44 if dlt, _, err = k.GetStringValue("Dlt"); err != nil {
45 return false, err
46 }
47 }
48
49 if std != stdname {
50 return false, nil
51 }
52 if dlt != dstname && dstname != stdname {
53 return false, nil
54 }
55 return true, nil
56 }
57
58
59
60 func toEnglishName(stdname, dstname string) (string, error) {
61 k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones`, registry.ENUMERATE_SUB_KEYS|registry.QUERY_VALUE)
62 if err != nil {
63 return "", err
64 }
65 defer k.Close()
66
67 names, err := k.ReadSubKeyNames()
68 if err != nil {
69 return "", err
70 }
71 for _, name := range names {
72 matched, err := matchZoneKey(k, name, stdname, dstname)
73 if err == nil && matched {
74 return name, nil
75 }
76 }
77 return "", errors.New(`English name for time zone "` + stdname + `" not found in registry`)
78 }
79
80
81 func extractCAPS(desc string) string {
82 var short []rune
83 for _, c := range desc {
84 if 'A' <= c && c <= 'Z' {
85 short = append(short, c)
86 }
87 }
88 return string(short)
89 }
90
91
92 func abbrev(z *syscall.Timezoneinformation) (std, dst string) {
93 stdName := syscall.UTF16ToString(z.StandardName[:])
94 a, ok := abbrs[stdName]
95 if !ok {
96 dstName := syscall.UTF16ToString(z.DaylightName[:])
97
98 englishName, err := toEnglishName(stdName, dstName)
99 if err == nil {
100 a, ok = abbrs[englishName]
101 if ok {
102 return a.std, a.dst
103 }
104 }
105
106 return extractCAPS(stdName), extractCAPS(dstName)
107 }
108 return a.std, a.dst
109 }
110
111
112
113
114 func pseudoUnix(year int, d *syscall.Systemtime) int64 {
115
116
117
118
119
120 day := 1
121 t := Date(year, Month(d.Month), day, int(d.Hour), int(d.Minute), int(d.Second), 0, UTC)
122 i := int(d.DayOfWeek) - int(t.Weekday())
123 if i < 0 {
124 i += 7
125 }
126 day += i
127 if week := int(d.Day) - 1; week < 4 {
128 day += week * 7
129 } else {
130
131 day += 4 * 7
132 if day > daysIn(Month(d.Month), year) {
133 day -= 7
134 }
135 }
136 return t.sec() + int64(day-1)*secondsPerDay + internalToUnix
137 }
138
139 func initLocalFromTZI(i *syscall.Timezoneinformation) {
140 l := &localLoc
141
142 l.name = "Local"
143
144 nzone := 1
145 if i.StandardDate.Month > 0 {
146 nzone++
147 }
148 l.zone = make([]zone, nzone)
149
150 stdname, dstname := abbrev(i)
151
152 std := &l.zone[0]
153 std.name = stdname
154 if nzone == 1 {
155
156 std.offset = -int(i.Bias) * 60
157 l.cacheStart = alpha
158 l.cacheEnd = omega
159 l.cacheZone = std
160 l.tx = make([]zoneTrans, 1)
161 l.tx[0].when = l.cacheStart
162 l.tx[0].index = 0
163 return
164 }
165
166
167
168
169 std.offset = -int(i.Bias+i.StandardBias) * 60
170
171 dst := &l.zone[1]
172 dst.name = dstname
173 dst.offset = -int(i.Bias+i.DaylightBias) * 60
174 dst.isDST = true
175
176
177
178 d0 := &i.StandardDate
179 d1 := &i.DaylightDate
180 i0 := 0
181 i1 := 1
182 if d0.Month > d1.Month {
183 d0, d1 = d1, d0
184 i0, i1 = i1, i0
185 }
186
187
188 l.tx = make([]zoneTrans, 400)
189
190 t := Now().UTC()
191 year := t.Year()
192 txi := 0
193 for y := year - 100; y < year+100; y++ {
194 tx := &l.tx[txi]
195 tx.when = pseudoUnix(y, d0) - int64(l.zone[i1].offset)
196 tx.index = uint8(i0)
197 txi++
198
199 tx = &l.tx[txi]
200 tx.when = pseudoUnix(y, d1) - int64(l.zone[i0].offset)
201 tx.index = uint8(i1)
202 txi++
203 }
204 }
205
206 var usPacific = syscall.Timezoneinformation{
207 Bias: 8 * 60,
208 StandardName: [32]uint16{
209 'P', 'a', 'c', 'i', 'f', 'i', 'c', ' ', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e',
210 },
211 StandardDate: syscall.Systemtime{Month: 11, Day: 1, Hour: 2},
212 DaylightName: [32]uint16{
213 'P', 'a', 'c', 'i', 'f', 'i', 'c', ' ', 'D', 'a', 'y', 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e',
214 },
215 DaylightDate: syscall.Systemtime{Month: 3, Day: 2, Hour: 2},
216 DaylightBias: -60,
217 }
218
219 var aus = syscall.Timezoneinformation{
220 Bias: -10 * 60,
221 StandardName: [32]uint16{
222 'A', 'U', 'S', ' ', 'E', 'a', 's', 't', 'e', 'r', 'n', ' ', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e',
223 },
224 StandardDate: syscall.Systemtime{Month: 4, Day: 1, Hour: 3},
225 DaylightName: [32]uint16{
226 'A', 'U', 'S', ' ', 'E', 'a', 's', 't', 'e', 'r', 'n', ' ', 'D', 'a', 'y', 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e',
227 },
228 DaylightDate: syscall.Systemtime{Month: 10, Day: 1, Hour: 2},
229 DaylightBias: -60,
230 }
231
232 func initLocal() {
233 var i syscall.Timezoneinformation
234 if _, err := syscall.GetTimeZoneInformation(&i); err != nil {
235 localLoc.name = "UTC"
236 return
237 }
238 initLocalFromTZI(&i)
239 }
240
View as plain text