diff options
| author | Rob Pike <r@golang.org> | 2009-06-09 09:53:44 -0700 |
|---|---|---|
| committer | Rob Pike <r@golang.org> | 2009-06-09 09:53:44 -0700 |
| commit | 7249ea4df2b4f12a4e7ed446f270cea87e4ffd34 (patch) | |
| tree | 7032a11d0cac2ae4d3e90f7a189b575b5a50f848 /src/lib/time | |
| parent | acf6ef7a82b3fe61516a1bac4563706552bdf078 (diff) | |
| download | golang-7249ea4df2b4f12a4e7ed446f270cea87e4ffd34.tar.gz | |
mv src/lib to src/pkg
tests: all.bash passes, gobuild still works, godoc still works.
R=rsc
OCL=30096
CL=30102
Diffstat (limited to 'src/lib/time')
| -rw-r--r-- | src/lib/time/Makefile | 77 | ||||
| -rw-r--r-- | src/lib/time/sleep.go | 17 | ||||
| -rw-r--r-- | src/lib/time/tick.go | 62 | ||||
| -rw-r--r-- | src/lib/time/tick_test.go | 29 | ||||
| -rw-r--r-- | src/lib/time/time.go | 372 | ||||
| -rw-r--r-- | src/lib/time/time_test.go | 85 | ||||
| -rw-r--r-- | src/lib/time/zoneinfo.go | 285 |
7 files changed, 0 insertions, 927 deletions
diff --git a/src/lib/time/Makefile b/src/lib/time/Makefile deleted file mode 100644 index 8d3c3b65f..000000000 --- a/src/lib/time/Makefile +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -# DO NOT EDIT. Automatically generated by gobuild. -# gobuild -m >Makefile - -D= - -include $(GOROOT)/src/Make.$(GOARCH) -AR=gopack - -default: packages - -clean: - rm -rf *.[$(OS)] *.a [$(OS)].out _obj - -test: packages - gotest - -coverage: packages - gotest - 6cov -g `pwd` | grep -v '_test\.go:' - -%.$O: %.go - $(GC) -I_obj $*.go - -%.$O: %.c - $(CC) $*.c - -%.$O: %.s - $(AS) $*.s - -O1=\ - sleep.$O\ - zoneinfo.$O\ - -O2=\ - time.$O\ - -O3=\ - tick.$O\ - - -phases: a1 a2 a3 -_obj$D/time.a: phases - -a1: $(O1) - $(AR) grc _obj$D/time.a sleep.$O zoneinfo.$O - rm -f $(O1) - -a2: $(O2) - $(AR) grc _obj$D/time.a time.$O - rm -f $(O2) - -a3: $(O3) - $(AR) grc _obj$D/time.a tick.$O - rm -f $(O3) - - -newpkg: clean - mkdir -p _obj$D - $(AR) grc _obj$D/time.a - -$(O1): newpkg -$(O2): a1 -$(O3): a2 -$(O4): a3 - -nuke: clean - rm -f $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/time.a - -packages: _obj$D/time.a - -install: packages - test -d $(GOROOT)/pkg && mkdir -p $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D - cp _obj$D/time.a $(GOROOT)/pkg/$(GOOS)_$(GOARCH)$D/time.a diff --git a/src/lib/time/sleep.go b/src/lib/time/sleep.go deleted file mode 100644 index 3bb76cf47..000000000 --- a/src/lib/time/sleep.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package time - -import ( - "os"; - "syscall"; - "unsafe"; -) - -// Sleep pauses the current goroutine for ns nanoseconds. -// It returns os.EINTR if interrupted. -func Sleep(ns int64) os.Error { - return os.ErrnoToError(syscall.Sleep(ns)); -} diff --git a/src/lib/time/tick.go b/src/lib/time/tick.go deleted file mode 100644 index 53e2234f8..000000000 --- a/src/lib/time/tick.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package time - -import ( - "syscall"; - "time"; - "unsafe"; -) - -// TODO(rsc): This implementation of time.Tick is a -// simple placeholder. Eventually, there will need to be -// a single central time server no matter how many tickers -// are active. There also needs to be a way to cancel a ticker. -// -// Also, if timeouts become part of the select statement, -// perhaps the Ticker is just: -// -// func Ticker(ns int64, c chan int64) { -// for { -// select { timeout ns: } -// nsec, err := time.Nanoseconds(); -// c <- nsec; -// } - -func ticker(ns int64, c chan int64) { - var tv syscall.Timeval; - now := time.Nanoseconds(); - when := now; - for { - when += ns; // next alarm - - // if c <- now took too long, skip ahead - if when < now { - // one big step - when += (now-when)/ns * ns; - } - for when <= now { - // little steps until when > now - when += ns - } - - time.Sleep(when - now); - now = time.Nanoseconds(); - c <- now; - } -} - -// Tick creates a synchronous channel that will send the time, in nanoseconds, -// every ns nanoseconds. It adjusts the intervals to make up for pauses in -// delivery of the ticks. -func Tick(ns int64) chan int64 { - if ns <= 0 { - return nil - } - c := make(chan int64); - go ticker(ns, c); - return c; -} - diff --git a/src/lib/time/tick_test.go b/src/lib/time/tick_test.go deleted file mode 100644 index 0667be679..000000000 --- a/src/lib/time/tick_test.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package time - -import ( - "testing"; - "time"; -) - -func TestTick(t *testing.T) { - const ( - Delta = 100*1e6; - Count = 10; - ); - c := Tick(Delta); - t0 := Nanoseconds(); - for i := 0; i < Count; i++ { - <-c; - } - t1 := Nanoseconds(); - ns := t1 - t0; - target := int64(Delta*Count); - slop := target*2/10; - if ns < target - slop || ns > target + slop { - t.Fatalf("%d ticks of %g ns took %g ns, expected %g", Count, float64(Delta), float64(ns), float64(target)); - } -} diff --git a/src/lib/time/time.go b/src/lib/time/time.go deleted file mode 100644 index ea9b66cbc..000000000 --- a/src/lib/time/time.go +++ /dev/null @@ -1,372 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// The time package provides functionality for measuring and -// displaying time. -package time - -import ( - "os"; - "time" -) - -// Seconds reports the number of seconds since the Unix epoch, -// January 1, 1970 00:00:00 UTC. -func Seconds() int64 { - sec, nsec, err := os.Time(); - if err != nil { - panic("time: os.Time: ", err.String()); - } - return sec -} - -// Nanoseconds reports the number of nanoseconds since the Unix epoch, -// January 1, 1970 00:00:00 UTC. -func Nanoseconds() int64 { - sec, nsec, err := os.Time(); - if err != nil { - panic("time: os.Time: ", err.String()); - } - return sec*1e9 + nsec -} - -// Days of the week. -const ( - Sunday = iota; - Monday; - Tuesday; - Wednesday; - Thursday; - Friday; - Saturday; -) - -// Time is the struct representing a parsed time value. -type Time struct { - Year int64; // 2008 is 2008 - Month, Day int; // Sep-17 is 9, 17 - Hour, Minute, Second int; // 10:43:12 is 10, 43, 12 - Weekday int; // Sunday, Monday, ... - ZoneOffset int; // seconds west of UTC - Zone string; -} - -var nonleapyear = []int{ - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -} -var leapyear = []int{ - 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -} - -func months(year int64) []int { - if year%4 == 0 && (year%100 != 0 || year%400 == 0) { - return leapyear - } - return nonleapyear -} - -const ( - secondsPerDay = 24*60*60; - - daysPer400Years = 365*400+97; - daysPer100Years = 365*100+24; - daysPer4Years = 365*4+1; - - days1970To2001 = 31*365+8; -) - -// SecondsToUTC converts sec, in number of seconds since the Unix epoch, -// into a parsed Time value in the UTC time zone. -func SecondsToUTC(sec int64) *Time { - t := new(Time); - - // Split into time and day. - day := sec/secondsPerDay; - sec -= day*secondsPerDay; - if sec < 0 { - day--; - sec += secondsPerDay - } - - // Time - t.Hour = int(sec/3600); - t.Minute = int((sec/60)%60); - t.Second = int(sec%60); - - // Day 0 = January 1, 1970 was a Thursday - t.Weekday = int((day + Thursday) % 7); - if t.Weekday < 0 { - t.Weekday += 7 - } - - // Change day from 0 = 1970 to 0 = 2001, - // to make leap year calculations easier - // (2001 begins 4-, 100-, and 400-year cycles ending in a leap year.) - day -= days1970To2001; - - year := int64(2001); - if day < 0 { - // Go back enough 400 year cycles to make day positive. - n := -day/daysPer400Years + 1; - year -= 400*n; - day += daysPer400Years*n; - } else { - // Cut off 400 year cycles. - n := day/daysPer400Years; - year += 400*n; - day -= daysPer400Years*n; - } - - // Cut off 100-year cycles - n := day/daysPer100Years; - year += 100*n; - day -= daysPer100Years*n; - - // Cut off 4-year cycles - n = day/daysPer4Years; - year += 4*n; - day -= daysPer4Years*n; - - // Cut off non-leap years. - n = day/365; - year += n; - day -= 365*n; - - t.Year = year; - - // If someone ever needs yearday, - // tyearday = day (+1?) - - months := months(year); - var m int; - yday := int(day); - for m = 0; m < 12 && yday >= months[m]; m++ { - yday -= months[m] - } - t.Month = m+1; - t.Day = yday+1; - t.Zone = "UTC"; - - return t; -} - -// UTC returns the current time as a parsed Time value in the UTC time zone. -func UTC() *Time { - return SecondsToUTC(Seconds()) -} - -// SecondsToLocalTime converts sec, in number of seconds since the Unix epoch, -// into a parsed Time value in the local time zone. -func SecondsToLocalTime(sec int64) *Time { - z, offset, err := time.lookupTimezone(sec); - if err != nil { - return SecondsToUTC(sec) - } - t := SecondsToUTC(sec+int64(offset)); - t.Zone = z; - t.ZoneOffset = offset; - return t -} - -// LocalTime returns the current time as a parsed Time value in the local time zone. -func LocalTime() *Time { - return SecondsToLocalTime(Seconds()) -} - -// Seconds returns the number of seconds since January 1, 1970 represented by the -// parsed Time value. -func (t *Time) Seconds() int64 { - // First, accumulate days since January 1, 2001. - // Using 2001 instead of 1970 makes the leap-year - // handling easier (see SecondsToUTC), because - // it is at the beginning of the 4-, 100-, and 400-year cycles. - day := int64(0); - - // Rewrite year to be >= 2001. - year := t.Year; - if year < 2001 { - n := (2001 - year)/400 + 1; - year += 400*n; - day -= daysPer400Years*n; - } - - // Add in days from 400-year cycles. - n := (year - 2001) / 400; - year -= 400*n; - day += daysPer400Years*n; - - // Add in 100-year cycles. - n = (year - 2001) / 100; - year -= 100*n; - day += daysPer100Years*n; - - // Add in 4-year cycles. - n = (year - 2001) / 4; - year -= 4*n; - day += daysPer4Years*n; - - // Add in non-leap years. - n = year - 2001; - day += 365*n; - - // Add in days this year. - months := months(t.Year); - for m := 0; m < t.Month-1; m++ { - day += int64(months[m]) - } - day += int64(t.Day - 1); - - // Convert days to seconds since January 1, 2001. - sec := day * secondsPerDay; - - // Add in time elapsed today. - sec += int64(t.Hour) * 3600; - sec += int64(t.Minute) * 60; - sec += int64(t.Second); - - // Convert from seconds since 2001 to seconds since 1970. - sec += days1970To2001 * secondsPerDay; - - // Account for local time zone. - sec -= int64(t.ZoneOffset); - return sec -} - -var longDayNames = []string{ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday" -} - -var shortDayNames = []string{ - "Sun", - "Mon", - "Tue", - "Wed", - "Thu", - "Fri", - "Sat" -} - -var shortMonthNames = []string{ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec" -} - -func copy(dst []byte, s string) { - for i := 0; i < len(s); i++ { - dst[i] = s[i] - } -} - -func decimal(dst []byte, n int) { - if n < 0 { - n = 0 - } - for i := len(dst)-1; i >= 0; i-- { - dst[i] = byte(n%10 + '0'); - n /= 10 - } -} - -func addString(buf []byte, bp int, s string) int { - n := len(s); - copy(buf[bp:bp+n], s); - return bp+n -} - -// Just enough of strftime to implement the date formats below. -// Not exported. -func format(t *Time, fmt string) string { - buf := make([]byte, 128); - bp := 0; - - for i := 0; i < len(fmt); i++ { - if fmt[i] == '%' { - i++; - switch fmt[i] { - case 'A': // %A full weekday name - bp = addString(buf, bp, longDayNames[t.Weekday]); - case 'a': // %a abbreviated weekday name - bp = addString(buf, bp, shortDayNames[t.Weekday]); - case 'b': // %b abbreviated month name - bp = addString(buf, bp, shortMonthNames[t.Month-1]); - case 'd': // %d day of month (01-31) - decimal(buf[bp:bp+2], t.Day); - bp += 2; - case 'e': // %e day of month ( 1-31) - if t.Day >= 10 { - decimal(buf[bp:bp+2], t.Day) - } else { - buf[bp] = ' '; - buf[bp+1] = byte(t.Day + '0') - } - bp += 2; - case 'H': // %H hour 00-23 - decimal(buf[bp:bp+2], t.Hour); - bp += 2; - case 'M': // %M minute 00-59 - decimal(buf[bp:bp+2], t.Minute); - bp += 2; - case 'S': // %S second 00-59 - decimal(buf[bp:bp+2], t.Second); - bp += 2; - case 'Y': // %Y year 2008 - decimal(buf[bp:bp+4], int(t.Year)); - bp += 4; - case 'y': // %y year 08 - decimal(buf[bp:bp+2], int(t.Year%100)); - bp += 2; - case 'Z': - bp = addString(buf, bp, t.Zone); - default: - buf[bp] = '%'; - buf[bp+1] = fmt[i]; - bp += 2 - } - } else { - buf[bp] = fmt[i]; - bp++; - } - } - return string(buf[0:bp]) -} - -// Asctime formats the parsed time value in the style of -// ANSI C asctime: Sun Nov 6 08:49:37 1994 -func (t *Time) Asctime() string { - return format(t, "%a %b %e %H:%M:%S %Y") -} - -// RFC850 formats the parsed time value in the style of -// RFC 850: Sunday, 06-Nov-94 08:49:37 UTC -func (t *Time) RFC850() string { - return format(t, "%A, %d-%b-%y %H:%M:%S %Z") -} - -// RFC1123 formats the parsed time value in the style of -// RFC 1123: Sun, 06 Nov 1994 08:49:37 UTC -func (t *Time) RFC1123() string { - return format(t, "%a, %d %b %Y %H:%M:%S %Z") -} - -// String formats the parsed time value in the style of -// date(1) - Sun Nov 6 08:49:37 UTC 1994 -func (t *Time) String() string { - return format(t, "%a %b %e %H:%M:%S %Z %Y") -} diff --git a/src/lib/time/time_test.go b/src/lib/time/time_test.go deleted file mode 100644 index 41e6736e8..000000000 --- a/src/lib/time/time_test.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package time - -import ( - "os"; - "testing"; - "time"; -) - -func init() { - // Force US Pacific time for daylight-savings - // tests below (localtests). Needs to be set - // before the first call into the time library. - os.Setenv("TZ", "US/Pacific"); -} - -type TimeTest struct { - seconds int64; - golden Time; -} - -var utctests = []TimeTest { - TimeTest{0, Time{1970, 1, 1, 0, 0, 0, Thursday, 0, "UTC"}}, - TimeTest{1221681866, Time{2008, 9, 17, 20, 4, 26, Wednesday, 0, "UTC"}}, - TimeTest{-1221681866, Time{1931, 4, 16, 3, 55, 34, Thursday, 0, "UTC"}}, - TimeTest{1e18, Time{31688740476, 10, 23, 1, 46, 40, Friday, 0, "UTC"}}, - TimeTest{-1e18, Time{-31688736537, 3, 10, 22, 13, 20, Tuesday, 0, "UTC"}}, - TimeTest{0x7fffffffffffffff, Time{292277026596, 12, 4, 15, 30, 7, Sunday, 0, "UTC"}}, - TimeTest{-0x8000000000000000, Time{-292277022657, 1, 27, 8, 29, 52, Sunday, 0, "UTC"}} -} - -var localtests = []TimeTest { - TimeTest{0, Time{1969, 12, 31, 16, 0, 0, Wednesday, -8*60*60, "PST"}}, - TimeTest{1221681866, Time{2008, 9, 17, 13, 4, 26, Wednesday, -7*60*60, "PDT"}} -} - -func same(t, u *Time) bool { - return t.Year == u.Year - && t.Month == u.Month - && t.Day == u.Day - && t.Hour == u.Hour - && t.Minute == u.Minute - && t.Second == u.Second - && t.Weekday == u.Weekday - && t.ZoneOffset == u.ZoneOffset - && t.Zone == u.Zone -} - -func TestSecondsToUTC(t *testing.T) { - for i := 0; i < len(utctests); i++ { - sec := utctests[i].seconds; - golden := &utctests[i].golden; - tm := SecondsToUTC(sec); - newsec := tm.Seconds(); - if newsec != sec { - t.Errorf("SecondsToUTC(%d).Seconds() = %d", sec, newsec); - } - if !same(tm, golden) { - t.Errorf("SecondsToUTC(%d):", sec); - t.Errorf(" want=%v", *golden); - t.Errorf(" have=%v", *tm); - } - } -} - -func TestSecondsToLocalTime(t *testing.T) { - for i := 0; i < len(localtests); i++ { - sec := localtests[i].seconds; - golden := &localtests[i].golden; - tm := SecondsToLocalTime(sec); - newsec := tm.Seconds(); - if newsec != sec { - t.Errorf("SecondsToLocalTime(%d).Seconds() = %d", sec, newsec); - } - if !same(tm, golden) { - t.Errorf("SecondsToLocalTime(%d):", sec); - t.Errorf(" want=%v", *golden); - t.Errorf(" have=%v", *tm); - } - } -} - diff --git a/src/lib/time/zoneinfo.go b/src/lib/time/zoneinfo.go deleted file mode 100644 index 751afc931..000000000 --- a/src/lib/time/zoneinfo.go +++ /dev/null @@ -1,285 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Parse "zoneinfo" time zone file. -// This is a fairly standard file format used on OS X, Linux, BSD, Sun, and others. -// See tzfile(5), http://en.wikipedia.org/wiki/Zoneinfo, -// and ftp://munnari.oz.au/pub/oldtz/ - -package time - -import ( - "io"; - "once"; - "os" -) - -const ( - maxFileSize = 8192; // actual files are closer to 1K - headerSize = 4+16+4*7; - - zoneDir = "/usr/share/zoneinfo/"; -) - -// Errors that can be generated recovering time zone information. -type TimeZoneError struct { - os.ErrorString -} - -var errShort = TimeZoneError{ "time: short zone file" } -var errInvalid = TimeZoneError{ "time: invalid zone file" } -var errLong = TimeZoneError{ "time: zone file too long" } - -// Simple I/O interface to binary blob of data. -type data struct { - p []byte; - error bool; -} - - -func (d *data) read(n int) []byte { - if len(d.p) < n { - d.p = nil; - d.error = true; - return nil; - } - p := d.p[0:n]; - d.p = d.p[n:len(d.p)]; - return p -} - -func (d *data) big4() (n uint32, ok bool) { - p := d.read(4); - if len(p) < 4 { - d.error = true; - return 0, false - } - return uint32(p[0]) << 24 | uint32(p[1]) << 16 | uint32(p[2]) << 8 | uint32(p[3]), true -} - -func (d *data) byte() (n byte, ok bool) { - p := d.read(1); - if len(p) < 1 { - d.error = true; - return 0, false - } - return p[0], true -} - - -// Make a string by stopping at the first NUL -func byteString(p []byte) string { - for i := 0; i < len(p); i++ { - if p[i] == 0 { - return string(p[0:i]) - } - } - return string(p) -} - -// Parsed representation -type zone struct { - utcoff int; - isdst bool; - name string; -} - -type zonetime struct { - time int32; // transition time, in seconds since 1970 GMT - zone *zone; // the zone that goes into effect at that time - isstd, isutc bool; // ignored - no idea what these mean -} - -func parseinfo(bytes []byte) (zt []zonetime, err os.Error) { - d := data{bytes, false}; - - // 4-byte magic "TZif" - if magic := d.read(4); string(magic) != "TZif" { - return nil, TimeZoneError{ "time: bad zone magic" } - } - - // 1-byte version, then 15 bytes of padding - var p []byte; - if p = d.read(16); len(p) != 16 || p[0] != 0 && p[0] != '2' { - return nil, TimeZoneError { "time: bad zone file version" } - } - vers := p[0]; - - // six big-endian 32-bit integers: - // number of UTC/local indicators - // number of standard/wall indicators - // number of leap seconds - // number of transition times - // number of local time zones - // number of characters of time zone abbrev strings - const ( - NUTCLocal = iota; - NStdWall; - NLeap; - NTime; - NZone; - NChar - ) - var n [6]int; - for i := 0; i < 6; i++ { - nn, ok := d.big4(); - if !ok { - return nil, errShort - } - n[i] = int(nn); - } - - // Transition times. - txtimes := data{d.read(n[NTime]*4), false}; - - // Time zone indices for transition times. - txzones := d.read(n[NTime]); - - // Zone info structures - zonedata := data{d.read(n[NZone]*6), false}; - - // Time zone abbreviations. - abbrev := d.read(n[NChar]); - - // Leap-second time pairs - leapdata := data{d.read(n[NLeap]*8), false}; - - // Whether tx times associated with local time types - // are specified as standard time or wall time. - isstd := d.read(n[NStdWall]); - - // Whether tx times associated with local time types - // are specified as UTC or local time. - isutc := d.read(n[NUTCLocal]); - - if d.error { // ran out of data - return nil, errShort - } - - // If version == 2, the entire file repeats, this time using - // 8-byte ints for txtimes and leap seconds. - // We won't need those until 2106. - - // Now we can build up a useful data structure. - // First the zone information. - // utcoff[4] isdst[1] nameindex[1] - z := make([]zone, n[NZone]); - for i := 0; i < len(z); i++ { - var ok bool; - var n uint32; - if n, ok = zonedata.big4(); !ok { - return nil, errShort - } - z[i].utcoff = int(n); - var b byte; - if b, ok = zonedata.byte(); !ok { - return nil, errShort - } - z[i].isdst = b != 0; - if b, ok = zonedata.byte(); !ok || int(b) >= len(abbrev) { - return nil, errInvalid - } - z[i].name = byteString(abbrev[b:len(abbrev)]) - } - - // Now the transition time info. - zt = make([]zonetime, n[NTime]); - for i := 0; i < len(zt); i++ { - var ok bool; - var n uint32; - if n, ok = txtimes.big4(); !ok { - return nil, errShort - } - zt[i].time = int32(n); - if int(txzones[i]) >= len(z) { - return nil, errInvalid - } - zt[i].zone = &z[txzones[i]]; - if i < len(isstd) { - zt[i].isstd = isstd[i] != 0 - } - if i < len(isutc) { - zt[i].isutc = isutc[i] != 0 - } - } - return zt, nil -} - -func readfile(name string, max int) (p []byte, err os.Error) { - f, e := os.Open(name, os.O_RDONLY, 0); - if e != nil { - return nil, e; - } - p = make([]byte, max); - n, err1 := io.FullRead(f, p); - f.Close(); - if err1 == nil { // too long - return nil, errLong; - } - if err1 != io.ErrEOF { - return nil, err1; - } - return p[0:n], nil; -} - -func readinfofile(name string) ([]zonetime, os.Error) { - buf, err := readfile(name, maxFileSize); - if err != nil { - goto Error; - } - tx, err := parseinfo(buf); - if err != nil { - goto Error; - } - return tx, nil; - -Error: - if tzerr, ok := err.(TimeZoneError); ok { - tzerr.ErrorString = os.ErrorString(tzerr.String() + ": " + name) - } - return nil, err -} - -var zones []zonetime -var zoneerr os.Error - -func setupZone() { - // consult $TZ to find the time zone to use. - // no $TZ means use the system default /etc/localtime. - // $TZ="" means use UTC. - // $TZ="foo" means use /usr/share/zoneinfo/foo. - - tz, err := os.Getenv("TZ"); - var file string; - switch { - case err == os.ENOENV: - zones, zoneerr = readinfofile("/etc/localtime"); - case err != nil: - zoneerr = err; - case len(tz) > 0: - zones, zoneerr = readinfofile(zoneDir + tz); - case len(tz) == 0: - // do nothing: use UTC - } -} - -func lookupTimezone(sec int64) (zone string, offset int, err os.Error) { - once.Do(setupZone); - if zoneerr != nil || len(zones) == 0 { - return "UTC", 0, zoneerr - } - - // Binary search for entry with largest time <= sec - tz := zones; - for len(tz) > 1 { - m := len(tz)/2; - if sec < int64(tz[m].time) { - tz = tz[0:m] - } else { - tz = tz[m:len(tz)] - } - } - z := tz[0].zone; - return z.name, z.utcoff, nil -} |
