| // Copyright 2013 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| //go:build ignore | |
| // | |
| // usage: | |
| // | |
| // go run genzabbrs.go -output zoneinfo_abbrs_windows.go | |
| // | |
| package main | |
| import ( | |
| "bytes" | |
| "encoding/xml" | |
| "flag" | |
| "go/format" | |
| "io" | |
| "log" | |
| "net/http" | |
| "os" | |
| "slices" | |
| "strings" | |
| "text/template" | |
| "time" | |
| ) | |
| var filename = flag.String("output", "zoneinfo_abbrs_windows.go", "output file name") | |
| // getAbbrs finds timezone abbreviations (standard and daylight saving time) | |
| // for location l. | |
| func getAbbrs(l *time.Location) (st, dt string) { | |
| t := time.Date(time.Now().Year(), 0, 1, 0, 0, 0, 0, l) | |
| abbr1, off1 := t.Zone() | |
| for i := 0; i < 12; i++ { | |
| t = t.AddDate(0, 1, 0) | |
| abbr2, off2 := t.Zone() | |
| if abbr1 != abbr2 { | |
| if off2-off1 < 0 { // southern hemisphere | |
| abbr1, abbr2 = abbr2, abbr1 | |
| } | |
| return abbr1, abbr2 | |
| } | |
| } | |
| return abbr1, abbr1 | |
| } | |
| type zone struct { | |
| WinName string | |
| UnixName string | |
| StTime string | |
| DSTime string | |
| } | |
| const wzURL = "https://raw.githubusercontent.com/unicode-org/cldr/main/common/supplemental/windowsZones.xml" | |
| type MapZone struct { | |
| Other string `xml:"other,attr"` | |
| Territory string `xml:"territory,attr"` | |
| Type string `xml:"type,attr"` | |
| } | |
| type SupplementalData struct { | |
| Zones []MapZone `xml:"windowsZones>mapTimezones>mapZone"` | |
| } | |
| func readWindowsZones() ([]*zone, error) { | |
| r, err := http.Get(wzURL) | |
| if err != nil { | |
| return nil, err | |
| } | |
| defer r.Body.Close() | |
| data, err := io.ReadAll(r.Body) | |
| if err != nil { | |
| return nil, err | |
| } | |
| var sd SupplementalData | |
| err = xml.Unmarshal(data, &sd) | |
| if err != nil { | |
| return nil, err | |
| } | |
| zs := make([]*zone, 0) | |
| for _, z := range sd.Zones { | |
| if z.Territory != "001" { | |
| // to avoid dups. I don't know why. | |
| continue | |
| } | |
| l, err := time.LoadLocation(z.Type) | |
| if err != nil { | |
| return nil, err | |
| } | |
| st, dt := getAbbrs(l) | |
| zs = append(zs, &zone{ | |
| WinName: z.Other, | |
| UnixName: z.Type, | |
| StTime: st, | |
| DSTime: dt, | |
| }) | |
| } | |
| return zs, nil | |
| } | |
| func main() { | |
| flag.Parse() | |
| zs, err := readWindowsZones() | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| slices.SortFunc(zs, func(a, b *zone) int { | |
| return strings.Compare(a.UnixName, b.UnixName) | |
| }) | |
| var v = struct { | |
| URL string | |
| Zs []*zone | |
| }{ | |
| wzURL, | |
| zs, | |
| } | |
| var buf bytes.Buffer | |
| err = template.Must(template.New("prog").Parse(prog)).Execute(&buf, v) | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| data, err := format.Source(buf.Bytes()) | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| err = os.WriteFile(*filename, data, 0644) | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| } | |
| const prog = ` | |
| // Copyright 2013 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| // Code generated by genzabbrs.go; DO NOT EDIT. | |
| // Based on information from {{.URL}} | |
| package time | |
| type abbr struct { | |
| std string | |
| dst string | |
| } | |
| var abbrs = map[string]abbr{ | |
| {{range .Zs}} "{{.WinName}}": {"{{.StTime}}", "{{.DSTime}}"}, // {{.UnixName}} | |
| {{end}}} | |
| ` |