1// Copyright 2013 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. 4 5//go:build ignore 6 7// 8// usage: 9// 10// go run genzabbrs.go -output zoneinfo_abbrs_windows.go 11// 12 13package main 14 15import ( 16 "bytes" 17 "encoding/xml" 18 "flag" 19 "go/format" 20 "io" 21 "log" 22 "net/http" 23 "os" 24 "slices" 25 "strings" 26 "text/template" 27 "time" 28) 29 30var filename = flag.String("output", "zoneinfo_abbrs_windows.go", "output file name") 31 32// getAbbrs finds timezone abbreviations (standard and daylight saving time) 33// for location l. 34func getAbbrs(l *time.Location) (st, dt string) { 35 t := time.Date(time.Now().Year(), 0, 1, 0, 0, 0, 0, l) 36 abbr1, off1 := t.Zone() 37 for i := 0; i < 12; i++ { 38 t = t.AddDate(0, 1, 0) 39 abbr2, off2 := t.Zone() 40 if abbr1 != abbr2 { 41 if off2-off1 < 0 { // southern hemisphere 42 abbr1, abbr2 = abbr2, abbr1 43 } 44 return abbr1, abbr2 45 } 46 } 47 return abbr1, abbr1 48} 49 50type zone struct { 51 WinName string 52 UnixName string 53 StTime string 54 DSTime string 55} 56 57const wzURL = "https://raw.githubusercontent.com/unicode-org/cldr/main/common/supplemental/windowsZones.xml" 58 59type MapZone struct { 60 Other string `xml:"other,attr"` 61 Territory string `xml:"territory,attr"` 62 Type string `xml:"type,attr"` 63} 64 65type SupplementalData struct { 66 Zones []MapZone `xml:"windowsZones>mapTimezones>mapZone"` 67} 68 69func readWindowsZones() ([]*zone, error) { 70 r, err := http.Get(wzURL) 71 if err != nil { 72 return nil, err 73 } 74 defer r.Body.Close() 75 76 data, err := io.ReadAll(r.Body) 77 if err != nil { 78 return nil, err 79 } 80 81 var sd SupplementalData 82 err = xml.Unmarshal(data, &sd) 83 if err != nil { 84 return nil, err 85 } 86 zs := make([]*zone, 0) 87 for _, z := range sd.Zones { 88 if z.Territory != "001" { 89 // to avoid dups. I don't know why. 90 continue 91 } 92 l, err := time.LoadLocation(z.Type) 93 if err != nil { 94 return nil, err 95 } 96 st, dt := getAbbrs(l) 97 zs = append(zs, &zone{ 98 WinName: z.Other, 99 UnixName: z.Type, 100 StTime: st, 101 DSTime: dt, 102 }) 103 } 104 return zs, nil 105} 106 107func main() { 108 flag.Parse() 109 zs, err := readWindowsZones() 110 if err != nil { 111 log.Fatal(err) 112 } 113 slices.SortFunc(zs, func(a, b *zone) int { 114 return strings.Compare(a.UnixName, b.UnixName) 115 }) 116 var v = struct { 117 URL string 118 Zs []*zone 119 }{ 120 wzURL, 121 zs, 122 } 123 var buf bytes.Buffer 124 err = template.Must(template.New("prog").Parse(prog)).Execute(&buf, v) 125 if err != nil { 126 log.Fatal(err) 127 } 128 data, err := format.Source(buf.Bytes()) 129 if err != nil { 130 log.Fatal(err) 131 } 132 err = os.WriteFile(*filename, data, 0644) 133 if err != nil { 134 log.Fatal(err) 135 } 136} 137 138const prog = ` 139// Copyright 2013 The Go Authors. All rights reserved. 140// Use of this source code is governed by a BSD-style 141// license that can be found in the LICENSE file. 142 143// Code generated by genzabbrs.go; DO NOT EDIT. 144// Based on information from {{.URL}} 145 146package time 147 148type abbr struct { 149 std string 150 dst string 151} 152 153var abbrs = map[string]abbr{ 154{{range .Zs}} "{{.WinName}}": {"{{.StTime}}", "{{.DSTime}}"}, // {{.UnixName}} 155{{end}}} 156 157` 158