summaryrefslogtreecommitdiff
path: root/timelocs.go
blob: 10b0f3362bc37aa3ecdec219d8cb5e62025c1373 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package main

import (
	"archive/zip"
	"log"
	"os"
	"path"
	"runtime"
	"sort"
	"sync"
	"time"
)

var timeLocs []string
var tlOnce sync.Once

func findfiles(p, prefix string, files []string) []string {
	d, err := os.Open(p)
	if err != nil {
		return files
	}
	defer d.Close()

	infos, err := d.Readdir(-1)
	if err != nil {
		return files
	}

	for _, info := range infos {
		if info.Mode().IsRegular() {
			files = append(files, prefix+info.Name())
		} else if info.IsDir() {
			files = findfiles(path.Join(p, info.Name()), info.Name()+"/", files)
		}
	}

	return files
}

func listTimeLocations() ([]string, error) {
	for _, p := range []string{"/usr/share/zoneinfo", "/usr/share/lib/zoneinfo", "/usr/lib/locale/TZ"} {
		files := findfiles(p, "", nil)
		duprem := make(map[string]bool)
		for _, loc := range files {
			if _, err := time.LoadLocation(loc); err == nil {
				duprem[loc] = true
			}
		}
		var locs []string
		for loc := range duprem {
			locs = append(locs, loc)
		}
		if len(locs) > 0 {
			sort.Strings(locs)
			return locs, nil
		}
	}

	zoneinfoZip := path.Join(runtime.GOROOT(), "lib", "time", "zoneinfo.zip")
	z, err := zip.OpenReader(zoneinfoZip)
	if err != nil {
		return nil, err
	}
	defer z.Close()

	locs := []string{}
	for _, f := range z.File {
		if f.Name[len(f.Name)-1] == '/' {
			continue
		}
		locs = append(locs, f.Name)
	}

	sort.Strings(locs)
	return locs, nil
}

func loadTimeLocs() {
	tlOnce.Do(func() {
		var err error
		if timeLocs, err = listTimeLocations(); err != nil {
			log.Fatalf("Could not load time locations: %s", err)
		}
	})
}