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.
15 func isSpace(r rune
) bool {
16 return r
== ' ' || r
== '\t' || r
== '\n'
19 // Copied from strings to avoid a dependency.
20 func fields(s
string) []string {
21 // First count the fields.
24 for _
, rune
:= range s
{
26 inField
= !isSpace(rune
)
27 if inField
&& !wasInField
{
33 a
:= make([]string, n
)
35 fieldStart
:= -1 // Set to -1 when looking for start of field.
36 for i
, rune
:= range s
{
39 a
[na
] = s
[fieldStart
:i
]
43 } else if fieldStart
== -1 {
47 if fieldStart
>= 0 { // Last field might end at EOF.
48 a
[na
] = s
[fieldStart
:]
53 func loadZoneDataPlan9(s
string) (l
*Location
, err error
) {
56 if len(f
) == 2 && f
[0] == "GMT" {
64 // standard timezone offset
69 zones
[0] = zone
{name
: f
[0], offset
: o
, isDST
: false}
71 // alternate timezone offset
76 zones
[1] = zone
{name
: f
[2], offset
: o
, isDST
: true}
78 // transition time pairs
81 for i
:= 0; i
< len(f
); i
++ {
91 tx
= append(tx
, zoneTrans
{when
: int64(t
), index
: uint8(zi
)})
94 // Committed to succeed.
95 l
= &Location
{zone
: zones
[:], tx
: tx
}
97 // Fill in the cache with information about right now,
98 // since that will be the most common lookup.
101 if tx
[i
].when
<= sec
&& (i
+1 == len(tx
) || sec
< tx
[i
+1].when
) {
102 l
.cacheStart
= tx
[i
].when
103 l
.cacheEnd
= 1<<63 - 1
105 l
.cacheEnd
= tx
[i
+1].when
107 l
.cacheZone
= &l
.zone
[tx
[i
].index
]
114 func loadZoneFilePlan9(name
string) (*Location
, error
) {
115 b
, err
:= readFile(name
)
119 return loadZoneDataPlan9(string(b
))
122 func initTestingZone() {
123 z
, err
:= loadLocation("America/Los_Angeles")
125 panic("cannot load America/Los_Angeles for testing: " + err
.Error())
132 t
, ok
:= syscall
.Getenv("timezone")
134 if z
, err
:= loadZoneDataPlan9(t
); err
== nil {
139 if z
, err
:= loadZoneFilePlan9("/adm/timezone/local"); err
== nil {
141 localLoc
.name
= "Local"
147 localLoc
.name
= "UTC"
150 func loadLocation(name
string) (*Location
, error
) {
151 if z
, err
:= loadZoneFile(runtime
.GOROOT()+"/lib/time/zoneinfo.zip", name
); err
== nil {
155 return nil, errors
.New("unknown time zone " + name
)
158 func forceZipFileForTesting(zipOnly
bool) {
159 // We only use the zip file anyway.