Source file src/time/genzabbrs.go

     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  
    13  package main
    14  
    15  import (
    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  
    30  var 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.
    34  func 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  
    50  type zone struct {
    51  	WinName  string
    52  	UnixName string
    53  	StTime   string
    54  	DSTime   string
    55  }
    56  
    57  const wzURL = "https://raw.githubusercontent.com/unicode-org/cldr/main/common/supplemental/windowsZones.xml"
    58  
    59  type MapZone struct {
    60  	Other     string `xml:"other,attr"`
    61  	Territory string `xml:"territory,attr"`
    62  	Type      string `xml:"type,attr"`
    63  }
    64  
    65  type SupplementalData struct {
    66  	Zones []MapZone `xml:"windowsZones>mapTimezones>mapZone"`
    67  }
    68  
    69  func 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  
   107  func 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  
   138  const 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  
   146  package time
   147  
   148  type abbr struct {
   149  	std string
   150  	dst string
   151  }
   152  
   153  var abbrs = map[string]abbr{
   154  {{range .Zs}}	"{{.WinName}}": {"{{.StTime}}", "{{.DSTime}}"}, // {{.UnixName}}
   155  {{end}}}
   156  
   157  `
   158  

View as plain text