github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/time/genzabbrs.go (about)

     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  `