...

Source file src/time/zoneinfo_plan9.go

     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.
     4	
     5	// Parse Plan 9 timezone(2) files.
     6	
     7	package time
     8	
     9	import (
    10		"runtime"
    11		"syscall"
    12	)
    13	
    14	var zoneSources = []string{
    15		runtime.GOROOT() + "/lib/time/zoneinfo.zip",
    16	}
    17	
    18	func isSpace(r rune) bool {
    19		return r == ' ' || r == '\t' || r == '\n'
    20	}
    21	
    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++
    32			}
    33		}
    34	
    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
    45				}
    46			} else if fieldStart == -1 {
    47				fieldStart = i
    48			}
    49		}
    50		if fieldStart >= 0 { // Last field might end at EOF.
    51			a[na] = s[fieldStart:]
    52		}
    53		return a
    54	}
    55	
    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
    61			}
    62			return nil, badData
    63		}
    64	
    65		var zones [2]zone
    66	
    67		// standard timezone offset
    68		o, err := atoi(f[1])
    69		if err != nil {
    70			return nil, badData
    71		}
    72		zones[0] = zone{name: f[0], offset: o, isDST: false}
    73	
    74		// alternate timezone offset
    75		o, err = atoi(f[3])
    76		if err != nil {
    77			return nil, badData
    78		}
    79		zones[1] = zone{name: f[2], offset: o, isDST: true}
    80	
    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
    88			}
    89			t, err := atoi(f[i])
    90			if err != nil {
    91				return nil, badData
    92			}
    93			t -= zones[0].offset
    94			tx = append(tx, zoneTrans{when: int64(t), index: uint8(zi)})
    95		}
    96	
    97		// Committed to succeed.
    98		l = &Location{zone: zones[:], tx: tx}
    99	
   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
   109				}
   110				l.cacheZone = &l.zone[tx[i].index]
   111			}
   112		}
   113	
   114		return l, nil
   115	}
   116	
   117	func loadZoneFilePlan9(name string) (*Location, error) {
   118		b, err := readFile(name)
   119		if err != nil {
   120			return nil, err
   121		}
   122		return loadZoneDataPlan9(string(b))
   123	}
   124	
   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
   131			}
   132		} else {
   133			if z, err := loadZoneFilePlan9("/adm/timezone/local"); err == nil {
   134				localLoc = *z
   135				localLoc.name = "Local"
   136				return
   137			}
   138		}
   139	
   140		// Fall back to UTC.
   141		localLoc.name = "UTC"
   142	}
   143	

View as plain text