Home | History | Annotate | Download | only in time
      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