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