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 const wzURL = "http://unicode.org/cldr/data/common/supplemental/windowsZones.xml"
     56 
     57 type MapZone struct {
     58 	Other     string `xml:"other,attr"`
     59 	Territory string `xml:"territory,attr"`
     60 	Type      string `xml:"type,attr"`
     61 }
     62 
     63 type SupplementalData struct {
     64 	Zones []MapZone `xml:"windowsZones>mapTimezones>mapZone"`
     65 }
     66 
     67 func readWindowsZones() ([]*zone, error) {
     68 	r, err := http.Get(wzURL)
     69 	if err != nil {
     70 		return nil, err
     71 	}
     72 	defer r.Body.Close()
     73 
     74 	data, err := ioutil.ReadAll(r.Body)
     75 	if err != nil {
     76 		return nil, err
     77 	}
     78 
     79 	var sd SupplementalData
     80 	err = xml.Unmarshal(data, &sd)
     81 	if err != nil {
     82 		return nil, err
     83 	}
     84 	zs := make([]*zone, 0)
     85 	for _, z := range sd.Zones {
     86 		if z.Territory != "001" {
     87 			// to avoid dups. I don't know why.
     88 			continue
     89 		}
     90 		l, err := time.LoadLocation(z.Type)
     91 		if err != nil {
     92 			return nil, err
     93 		}
     94 		st, dt := getAbbrs(l)
     95 		zs = append(zs, &zone{
     96 			WinName:  z.Other,
     97 			UnixName: z.Type,
     98 			StTime:   st,
     99 			DSTime:   dt,
    100 		})
    101 	}
    102 	return zs, nil
    103 }
    104 
    105 func main() {
    106 	flag.Parse()
    107 	zs, err := readWindowsZones()
    108 	if err != nil {
    109 		log.Fatal(err)
    110 	}
    111 	sort.Slice(zs, func(i, j int) bool {
    112 		return zs[i].UnixName < zs[j].UnixName
    113 	})
    114 	var v = struct {
    115 		URL string
    116 		Zs  []*zone
    117 	}{
    118 		wzURL,
    119 		zs,
    120 	}
    121 	var buf bytes.Buffer
    122 	err = template.Must(template.New("prog").Parse(prog)).Execute(&buf, v)
    123 	if err != nil {
    124 		log.Fatal(err)
    125 	}
    126 	data, err := format.Source(buf.Bytes())
    127 	if err != nil {
    128 		log.Fatal(err)
    129 	}
    130 	err = ioutil.WriteFile(*filename, data, 0644)
    131 	if err != nil {
    132 		log.Fatal(err)
    133 	}
    134 }
    135 
    136 const prog = `
    137 // Copyright 2013 The Go Authors. All rights reserved.
    138 // Use of this source code is governed by a BSD-style
    139 // license that can be found in the LICENSE file.
    140 
    141 // Code generated by genzabbrs.go; DO NOT EDIT.
    142 // Based on information from {{.URL}}
    143 
    144 package time
    145 
    146 type abbr struct {
    147 	std string
    148 	dst string
    149 }
    150 
    151 var abbrs = map[string]abbr{
    152 {{range .Zs}}	"{{.WinName}}": {"{{.StTime}}", "{{.DSTime}}"}, // {{.UnixName}}
    153 {{end}}}
    154 
    155 `
    156