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