PR c++/85515
[official-gcc.git] / libgo / go / time / zoneinfo_plan9.go
blob4ae718c59e1fc0abc2f7bf13782e9885920f3b16
1 // Copyright 2011 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.
5 // Parse Plan 9 timezone(2) files.
7 package time
9 import (
10 "runtime"
11 "syscall"
14 var zoneSources = []string{
15 runtime.GOROOT() + "/lib/time/zoneinfo.zip",
18 func isSpace(r rune) bool {
19 return r == ' ' || r == '\t' || r == '\n'
22 // Copied from strings to avoid a dependency.
23 func fields(s string) []string {
24 // First count the fields.
25 n := 0
26 inField := false
27 for _, rune := range s {
28 wasInField := inField
29 inField = !isSpace(rune)
30 if inField && !wasInField {
31 n++
35 // Now create them.
36 a := make([]string, n)
37 na := 0
38 fieldStart := -1 // Set to -1 when looking for start of field.
39 for i, rune := range s {
40 if isSpace(rune) {
41 if fieldStart >= 0 {
42 a[na] = s[fieldStart:i]
43 na++
44 fieldStart = -1
46 } else if fieldStart == -1 {
47 fieldStart = i
50 if fieldStart >= 0 { // Last field might end at EOF.
51 a[na] = s[fieldStart:]
53 return a
56 func loadZoneDataPlan9(s string) (l *Location, err error) {
57 f := fields(s)
58 if len(f) < 4 {
59 if len(f) == 2 && f[0] == "GMT" {
60 return UTC, nil
62 return nil, badData
65 var zones [2]zone
67 // standard timezone offset
68 o, err := atoi(f[1])
69 if err != nil {
70 return nil, badData
72 zones[0] = zone{name: f[0], offset: o, isDST: false}
74 // alternate timezone offset
75 o, err = atoi(f[3])
76 if err != nil {
77 return nil, badData
79 zones[1] = zone{name: f[2], offset: o, isDST: true}
81 // transition time pairs
82 var tx []zoneTrans
83 f = f[4:]
84 for i := 0; i < len(f); i++ {
85 zi := 0
86 if i%2 == 0 {
87 zi = 1
89 t, err := atoi(f[i])
90 if err != nil {
91 return nil, badData
93 t -= zones[0].offset
94 tx = append(tx, zoneTrans{when: int64(t), index: uint8(zi)})
97 // Committed to succeed.
98 l = &Location{zone: zones[:], tx: tx}
100 // Fill in the cache with information about right now,
101 // since that will be the most common lookup.
102 sec, _, _ := now()
103 for i := range tx {
104 if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
105 l.cacheStart = tx[i].when
106 l.cacheEnd = omega
107 if i+1 < len(tx) {
108 l.cacheEnd = tx[i+1].when
110 l.cacheZone = &l.zone[tx[i].index]
114 return l, nil
117 func loadZoneFilePlan9(name string) (*Location, error) {
118 b, err := readFile(name)
119 if err != nil {
120 return nil, err
122 return loadZoneDataPlan9(string(b))
125 func initLocal() {
126 t, ok := syscall.Getenv("timezone")
127 if ok {
128 if z, err := loadZoneDataPlan9(t); err == nil {
129 localLoc = *z
130 return
132 } else {
133 if z, err := loadZoneFilePlan9("/adm/timezone/local"); err == nil {
134 localLoc = *z
135 localLoc.name = "Local"
136 return
140 // Fall back to UTC.
141 localLoc.name = "UTC"