summaryrefslogtreecommitdiff
path: root/src/pkg/time
diff options
context:
space:
mode:
authorTianon Gravi <admwiggin@gmail.com>2015-01-15 11:54:00 -0700
committerTianon Gravi <admwiggin@gmail.com>2015-01-15 11:54:00 -0700
commitf154da9e12608589e8d5f0508f908a0c3e88a1bb (patch)
treef8255d51e10c6f1e0ed69702200b966c9556a431 /src/pkg/time
parent8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff)
downloadgolang-upstream/1.4.tar.gz
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/pkg/time')
-rw-r--r--src/pkg/time/Makefile9
-rw-r--r--src/pkg/time/example_test.go160
-rw-r--r--src/pkg/time/export_test.go24
-rw-r--r--src/pkg/time/export_windows_test.go10
-rw-r--r--src/pkg/time/format.go1247
-rw-r--r--src/pkg/time/format_test.go517
-rw-r--r--src/pkg/time/genzabbrs.go145
-rw-r--r--src/pkg/time/internal_test.go92
-rw-r--r--src/pkg/time/sleep.go122
-rw-r--r--src/pkg/time/sleep_test.go393
-rw-r--r--src/pkg/time/sys_plan9.go76
-rw-r--r--src/pkg/time/sys_unix.go76
-rw-r--r--src/pkg/time/sys_windows.go73
-rw-r--r--src/pkg/time/tick.go56
-rw-r--r--src/pkg/time/tick_test.go78
-rw-r--r--src/pkg/time/time.go1206
-rw-r--r--src/pkg/time/time_test.go1081
-rw-r--r--src/pkg/time/zoneinfo.go287
-rw-r--r--src/pkg/time/zoneinfo_abbrs_windows.go115
-rw-r--r--src/pkg/time/zoneinfo_plan9.go160
-rw-r--r--src/pkg/time/zoneinfo_read.go343
-rw-r--r--src/pkg/time/zoneinfo_test.go63
-rw-r--r--src/pkg/time/zoneinfo_unix.go84
-rw-r--r--src/pkg/time/zoneinfo_windows.go270
-rw-r--r--src/pkg/time/zoneinfo_windows_test.go35
25 files changed, 0 insertions, 6722 deletions
diff --git a/src/pkg/time/Makefile b/src/pkg/time/Makefile
deleted file mode 100644
index cba58e4e0..000000000
--- a/src/pkg/time/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright 2013 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.
-
-genzabbrs: genzabbrs.go
- go build genzabbrs.go
-
-windows: genzabbrs
- ./genzabbrs | gofmt >zoneinfo_abbrs_windows.go
diff --git a/src/pkg/time/example_test.go b/src/pkg/time/example_test.go
deleted file mode 100644
index cfa5b38c5..000000000
--- a/src/pkg/time/example_test.go
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2011 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_test
-
-import (
- "fmt"
- "time"
-)
-
-func expensiveCall() {}
-
-func ExampleDuration() {
- t0 := time.Now()
- expensiveCall()
- t1 := time.Now()
- fmt.Printf("The call took %v to run.\n", t1.Sub(t0))
-}
-
-var c chan int
-
-func handle(int) {}
-
-func ExampleAfter() {
- select {
- case m := <-c:
- handle(m)
- case <-time.After(5 * time.Minute):
- fmt.Println("timed out")
- }
-}
-
-func ExampleSleep() {
- time.Sleep(100 * time.Millisecond)
-}
-
-func statusUpdate() string { return "" }
-
-func ExampleTick() {
- c := time.Tick(1 * time.Minute)
- for now := range c {
- fmt.Printf("%v %s\n", now, statusUpdate())
- }
-}
-
-func ExampleMonth() {
- _, month, day := time.Now().Date()
- if month == time.November && day == 10 {
- fmt.Println("Happy Go day!")
- }
-}
-
-func ExampleDate() {
- t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
- fmt.Printf("Go launched at %s\n", t.Local())
- // Output: Go launched at 2009-11-10 15:00:00 -0800 PST
-}
-
-func ExampleTime_Format() {
- // layout shows by example how the reference time should be represented.
- const layout = "Jan 2, 2006 at 3:04pm (MST)"
- t := time.Date(2009, time.November, 10, 15, 0, 0, 0, time.Local)
- fmt.Println(t.Format(layout))
- fmt.Println(t.UTC().Format(layout))
- // Output:
- // Nov 10, 2009 at 3:00pm (PST)
- // Nov 10, 2009 at 11:00pm (UTC)
-}
-
-func ExampleParse() {
- // longForm shows by example how the reference time would be represented in
- // the desired layout.
- const longForm = "Jan 2, 2006 at 3:04pm (MST)"
- t, _ := time.Parse(longForm, "Feb 3, 2013 at 7:54pm (PST)")
- fmt.Println(t)
-
- // shortForm is another way the reference time would be represented
- // in the desired layout; it has no time zone present.
- // Note: without explicit zone, returns time in UTC.
- const shortForm = "2006-Jan-02"
- t, _ = time.Parse(shortForm, "2013-Feb-03")
- fmt.Println(t)
-
- // Output:
- // 2013-02-03 19:54:00 -0800 PST
- // 2013-02-03 00:00:00 +0000 UTC
-}
-
-func ExampleParseInLocation() {
- loc, _ := time.LoadLocation("Europe/Berlin")
-
- const longForm = "Jan 2, 2006 at 3:04pm (MST)"
- t, _ := time.ParseInLocation(longForm, "Jul 9, 2012 at 5:02am (CEST)", loc)
- fmt.Println(t)
-
- // Note: without explicit zone, returns time in given location.
- const shortForm = "2006-Jan-02"
- t, _ = time.ParseInLocation(shortForm, "2012-Jul-09", loc)
- fmt.Println(t)
-
- // Output:
- // 2012-07-09 05:02:00 +0200 CEST
- // 2012-07-09 00:00:00 +0200 CEST
-}
-
-func ExampleTime_Round() {
- t := time.Date(0, 0, 0, 12, 15, 30, 918273645, time.UTC)
- round := []time.Duration{
- time.Nanosecond,
- time.Microsecond,
- time.Millisecond,
- time.Second,
- 2 * time.Second,
- time.Minute,
- 10 * time.Minute,
- time.Hour,
- }
-
- for _, d := range round {
- fmt.Printf("t.Round(%6s) = %s\n", d, t.Round(d).Format("15:04:05.999999999"))
- }
- // Output:
- // t.Round( 1ns) = 12:15:30.918273645
- // t.Round( 1us) = 12:15:30.918274
- // t.Round( 1ms) = 12:15:30.918
- // t.Round( 1s) = 12:15:31
- // t.Round( 2s) = 12:15:30
- // t.Round( 1m0s) = 12:16:00
- // t.Round( 10m0s) = 12:20:00
- // t.Round(1h0m0s) = 12:00:00
-}
-
-func ExampleTime_Truncate() {
- t, _ := time.Parse("2006 Jan 02 15:04:05", "2012 Dec 07 12:15:30.918273645")
- trunc := []time.Duration{
- time.Nanosecond,
- time.Microsecond,
- time.Millisecond,
- time.Second,
- 2 * time.Second,
- time.Minute,
- 10 * time.Minute,
- time.Hour,
- }
-
- for _, d := range trunc {
- fmt.Printf("t.Truncate(%6s) = %s\n", d, t.Truncate(d).Format("15:04:05.999999999"))
- }
-
- // Output:
- // t.Truncate( 1ns) = 12:15:30.918273645
- // t.Truncate( 1us) = 12:15:30.918273
- // t.Truncate( 1ms) = 12:15:30.918
- // t.Truncate( 1s) = 12:15:30
- // t.Truncate( 2s) = 12:15:30
- // t.Truncate( 1m0s) = 12:15:00
- // t.Truncate( 10m0s) = 12:10:00
- // t.Truncate(1h0m0s) = 12:00:00
-}
diff --git a/src/pkg/time/export_test.go b/src/pkg/time/export_test.go
deleted file mode 100644
index 6cd535f6b..000000000
--- a/src/pkg/time/export_test.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2013 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 (
- "sync"
-)
-
-func ResetLocalOnceForTest() {
- localOnce = sync.Once{}
- localLoc = Location{}
-}
-
-func ForceUSPacificForTesting() {
- ResetLocalOnceForTest()
- localOnce.Do(initTestingZone)
-}
-
-var (
- ForceZipFileForTesting = forceZipFileForTesting
- ParseTimeZone = parseTimeZone
-)
diff --git a/src/pkg/time/export_windows_test.go b/src/pkg/time/export_windows_test.go
deleted file mode 100644
index 7e689b829..000000000
--- a/src/pkg/time/export_windows_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2013 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
-
-func ForceAusForTesting() {
- ResetLocalOnceForTest()
- localOnce.Do(initAusTestingZone)
-}
diff --git a/src/pkg/time/format.go b/src/pkg/time/format.go
deleted file mode 100644
index 9f210ea27..000000000
--- a/src/pkg/time/format.go
+++ /dev/null
@@ -1,1247 +0,0 @@
-// Copyright 2010 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 "errors"
-
-// These are predefined layouts for use in Time.Format and Time.Parse.
-// The reference time used in the layouts is:
-// Mon Jan 2 15:04:05 MST 2006
-// which is Unix time 1136239445. Since MST is GMT-0700,
-// the reference time can be thought of as
-// 01/02 03:04:05PM '06 -0700
-// To define your own format, write down what the reference time would look
-// like formatted your way; see the values of constants like ANSIC,
-// StampMicro or Kitchen for examples. The model is to demonstrate what the
-// reference time looks like so that the Format and Parse methods can apply
-// the same transformation to a general time value.
-//
-// Within the format string, an underscore _ represents a space that may be
-// replaced by a digit if the following number (a day) has two digits; for
-// compatibility with fixed-width Unix time formats.
-//
-// A decimal point followed by one or more zeros represents a fractional
-// second, printed to the given number of decimal places. A decimal point
-// followed by one or more nines represents a fractional second, printed to
-// the given number of decimal places, with trailing zeros removed.
-// When parsing (only), the input may contain a fractional second
-// field immediately after the seconds field, even if the layout does not
-// signify its presence. In that case a decimal point followed by a maximal
-// series of digits is parsed as a fractional second.
-//
-// Numeric time zone offsets format as follows:
-// -0700 ±hhmm
-// -07:00 ±hh:mm
-// Replacing the sign in the format with a Z triggers
-// the ISO 8601 behavior of printing Z instead of an
-// offset for the UTC zone. Thus:
-// Z0700 Z or ±hhmm
-// Z07:00 Z or ±hh:mm
-const (
- ANSIC = "Mon Jan _2 15:04:05 2006"
- UnixDate = "Mon Jan _2 15:04:05 MST 2006"
- RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
- RFC822 = "02 Jan 06 15:04 MST"
- RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
- RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
- RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
- RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
- RFC3339 = "2006-01-02T15:04:05Z07:00"
- RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
- Kitchen = "3:04PM"
- // Handy time stamps.
- Stamp = "Jan _2 15:04:05"
- StampMilli = "Jan _2 15:04:05.000"
- StampMicro = "Jan _2 15:04:05.000000"
- StampNano = "Jan _2 15:04:05.000000000"
-)
-
-const (
- _ = iota
- stdLongMonth = iota + stdNeedDate // "January"
- stdMonth // "Jan"
- stdNumMonth // "1"
- stdZeroMonth // "01"
- stdLongWeekDay // "Monday"
- stdWeekDay // "Mon"
- stdDay // "2"
- stdUnderDay // "_2"
- stdZeroDay // "02"
- stdHour = iota + stdNeedClock // "15"
- stdHour12 // "3"
- stdZeroHour12 // "03"
- stdMinute // "4"
- stdZeroMinute // "04"
- stdSecond // "5"
- stdZeroSecond // "05"
- stdLongYear = iota + stdNeedDate // "2006"
- stdYear // "06"
- stdPM = iota + stdNeedClock // "PM"
- stdpm // "pm"
- stdTZ = iota // "MST"
- stdISO8601TZ // "Z0700" // prints Z for UTC
- stdISO8601SecondsTZ // "Z070000"
- stdISO8601ColonTZ // "Z07:00" // prints Z for UTC
- stdISO8601ColonSecondsTZ // "Z07:00:00"
- stdNumTZ // "-0700" // always numeric
- stdNumSecondsTz // "-070000"
- stdNumShortTZ // "-07" // always numeric
- stdNumColonTZ // "-07:00" // always numeric
- stdNumColonSecondsTZ // "-07:00:00"
- stdFracSecond0 // ".0", ".00", ... , trailing zeros included
- stdFracSecond9 // ".9", ".99", ..., trailing zeros omitted
-
- stdNeedDate = 1 << 8 // need month, day, year
- stdNeedClock = 2 << 8 // need hour, minute, second
- stdArgShift = 16 // extra argument in high bits, above low stdArgShift
- stdMask = 1<<stdArgShift - 1 // mask out argument
-)
-
-// std0x records the std values for "01", "02", ..., "06".
-var std0x = [...]int{stdZeroMonth, stdZeroDay, stdZeroHour12, stdZeroMinute, stdZeroSecond, stdYear}
-
-// startsWithLowerCase reports whether the string has a lower-case letter at the beginning.
-// Its purpose is to prevent matching strings like "Month" when looking for "Mon".
-func startsWithLowerCase(str string) bool {
- if len(str) == 0 {
- return false
- }
- c := str[0]
- return 'a' <= c && c <= 'z'
-}
-
-// nextStdChunk finds the first occurrence of a std string in
-// layout and returns the text before, the std string, and the text after.
-func nextStdChunk(layout string) (prefix string, std int, suffix string) {
- for i := 0; i < len(layout); i++ {
- switch c := int(layout[i]); c {
- case 'J': // January, Jan
- if len(layout) >= i+3 && layout[i:i+3] == "Jan" {
- if len(layout) >= i+7 && layout[i:i+7] == "January" {
- return layout[0:i], stdLongMonth, layout[i+7:]
- }
- if !startsWithLowerCase(layout[i+3:]) {
- return layout[0:i], stdMonth, layout[i+3:]
- }
- }
-
- case 'M': // Monday, Mon, MST
- if len(layout) >= i+3 {
- if layout[i:i+3] == "Mon" {
- if len(layout) >= i+6 && layout[i:i+6] == "Monday" {
- return layout[0:i], stdLongWeekDay, layout[i+6:]
- }
- if !startsWithLowerCase(layout[i+3:]) {
- return layout[0:i], stdWeekDay, layout[i+3:]
- }
- }
- if layout[i:i+3] == "MST" {
- return layout[0:i], stdTZ, layout[i+3:]
- }
- }
-
- case '0': // 01, 02, 03, 04, 05, 06
- if len(layout) >= i+2 && '1' <= layout[i+1] && layout[i+1] <= '6' {
- return layout[0:i], std0x[layout[i+1]-'1'], layout[i+2:]
- }
-
- case '1': // 15, 1
- if len(layout) >= i+2 && layout[i+1] == '5' {
- return layout[0:i], stdHour, layout[i+2:]
- }
- return layout[0:i], stdNumMonth, layout[i+1:]
-
- case '2': // 2006, 2
- if len(layout) >= i+4 && layout[i:i+4] == "2006" {
- return layout[0:i], stdLongYear, layout[i+4:]
- }
- return layout[0:i], stdDay, layout[i+1:]
-
- case '_': // _2
- if len(layout) >= i+2 && layout[i+1] == '2' {
- return layout[0:i], stdUnderDay, layout[i+2:]
- }
-
- case '3':
- return layout[0:i], stdHour12, layout[i+1:]
-
- case '4':
- return layout[0:i], stdMinute, layout[i+1:]
-
- case '5':
- return layout[0:i], stdSecond, layout[i+1:]
-
- case 'P': // PM
- if len(layout) >= i+2 && layout[i+1] == 'M' {
- return layout[0:i], stdPM, layout[i+2:]
- }
-
- case 'p': // pm
- if len(layout) >= i+2 && layout[i+1] == 'm' {
- return layout[0:i], stdpm, layout[i+2:]
- }
-
- case '-': // -070000, -07:00:00, -0700, -07:00, -07
- if len(layout) >= i+7 && layout[i:i+7] == "-070000" {
- return layout[0:i], stdNumSecondsTz, layout[i+7:]
- }
- if len(layout) >= i+9 && layout[i:i+9] == "-07:00:00" {
- return layout[0:i], stdNumColonSecondsTZ, layout[i+9:]
- }
- if len(layout) >= i+5 && layout[i:i+5] == "-0700" {
- return layout[0:i], stdNumTZ, layout[i+5:]
- }
- if len(layout) >= i+6 && layout[i:i+6] == "-07:00" {
- return layout[0:i], stdNumColonTZ, layout[i+6:]
- }
- if len(layout) >= i+3 && layout[i:i+3] == "-07" {
- return layout[0:i], stdNumShortTZ, layout[i+3:]
- }
-
- case 'Z': // Z070000, Z07:00:00, Z0700, Z07:00,
- if len(layout) >= i+7 && layout[i:i+7] == "Z070000" {
- return layout[0:i], stdISO8601SecondsTZ, layout[i+7:]
- }
- if len(layout) >= i+9 && layout[i:i+9] == "Z07:00:00" {
- return layout[0:i], stdISO8601ColonSecondsTZ, layout[i+9:]
- }
- if len(layout) >= i+5 && layout[i:i+5] == "Z0700" {
- return layout[0:i], stdISO8601TZ, layout[i+5:]
- }
- if len(layout) >= i+6 && layout[i:i+6] == "Z07:00" {
- return layout[0:i], stdISO8601ColonTZ, layout[i+6:]
- }
-
- case '.': // .000 or .999 - repeated digits for fractional seconds.
- if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
- ch := layout[i+1]
- j := i + 1
- for j < len(layout) && layout[j] == ch {
- j++
- }
- // String of digits must end here - only fractional second is all digits.
- if !isDigit(layout, j) {
- std := stdFracSecond0
- if layout[i+1] == '9' {
- std = stdFracSecond9
- }
- std |= (j - (i + 1)) << stdArgShift
- return layout[0:i], std, layout[j:]
- }
- }
- }
- }
- return layout, 0, ""
-}
-
-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",
-}
-
-var longMonthNames = []string{
- "---",
- "January",
- "February",
- "March",
- "April",
- "May",
- "June",
- "July",
- "August",
- "September",
- "October",
- "November",
- "December",
-}
-
-// match returns true if s1 and s2 match ignoring case.
-// It is assumed s1 and s2 are the same length.
-func match(s1, s2 string) bool {
- for i := 0; i < len(s1); i++ {
- c1 := s1[i]
- c2 := s2[i]
- if c1 != c2 {
- // Switch to lower-case; 'a'-'A' is known to be a single bit.
- c1 |= 'a' - 'A'
- c2 |= 'a' - 'A'
- if c1 != c2 || c1 < 'a' || c1 > 'z' {
- return false
- }
- }
- }
- return true
-}
-
-func lookup(tab []string, val string) (int, string, error) {
- for i, v := range tab {
- if len(val) >= len(v) && match(val[0:len(v)], v) {
- return i, val[len(v):], nil
- }
- }
- return -1, val, errBad
-}
-
-// appendUint appends the decimal form of x to b and returns the result.
-// If x is a single-digit number and pad != 0, appendUint inserts the pad byte
-// before the digit.
-// Duplicates functionality in strconv, but avoids dependency.
-func appendUint(b []byte, x uint, pad byte) []byte {
- if x < 10 {
- if pad != 0 {
- b = append(b, pad)
- }
- return append(b, byte('0'+x))
- }
- if x < 100 {
- b = append(b, byte('0'+x/10))
- b = append(b, byte('0'+x%10))
- return b
- }
-
- var buf [32]byte
- n := len(buf)
- if x == 0 {
- return append(b, '0')
- }
- for x >= 10 {
- n--
- buf[n] = byte(x%10 + '0')
- x /= 10
- }
- n--
- buf[n] = byte(x + '0')
- return append(b, buf[n:]...)
-}
-
-// Never printed, just needs to be non-nil for return by atoi.
-var atoiError = errors.New("time: invalid number")
-
-// Duplicates functionality in strconv, but avoids dependency.
-func atoi(s string) (x int, err error) {
- neg := false
- if s != "" && (s[0] == '-' || s[0] == '+') {
- neg = s[0] == '-'
- s = s[1:]
- }
- q, rem, err := leadingInt(s)
- x = int(q)
- if err != nil || rem != "" {
- return 0, atoiError
- }
- if neg {
- x = -x
- }
- return x, nil
-}
-
-// formatNano appends a fractional second, as nanoseconds, to b
-// and returns the result.
-func formatNano(b []byte, nanosec uint, n int, trim bool) []byte {
- u := nanosec
- var buf [9]byte
- for start := len(buf); start > 0; {
- start--
- buf[start] = byte(u%10 + '0')
- u /= 10
- }
-
- if n > 9 {
- n = 9
- }
- if trim {
- for n > 0 && buf[n-1] == '0' {
- n--
- }
- if n == 0 {
- return b
- }
- }
- b = append(b, '.')
- return append(b, buf[:n]...)
-}
-
-// String returns the time formatted using the format string
-// "2006-01-02 15:04:05.999999999 -0700 MST"
-func (t Time) String() string {
- return t.Format("2006-01-02 15:04:05.999999999 -0700 MST")
-}
-
-// Format returns a textual representation of the time value formatted
-// according to layout, which defines the format by showing how the reference
-// time,
-// Mon Jan 2 15:04:05 -0700 MST 2006
-// would be displayed if it were the value; it serves as an example of the
-// desired output. The same display rules will then be applied to the time
-// value.
-// Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard
-// and convenient representations of the reference time. For more information
-// about the formats and the definition of the reference time, see the
-// documentation for ANSIC and the other constants defined by this package.
-func (t Time) Format(layout string) string {
- var (
- name, offset, abs = t.locabs()
-
- year int = -1
- month Month
- day int
- hour int = -1
- min int
- sec int
-
- b []byte
- buf [64]byte
- )
- max := len(layout) + 10
- if max <= len(buf) {
- b = buf[:0]
- } else {
- b = make([]byte, 0, max)
- }
- // Each iteration generates one std value.
- for layout != "" {
- prefix, std, suffix := nextStdChunk(layout)
- if prefix != "" {
- b = append(b, prefix...)
- }
- if std == 0 {
- break
- }
- layout = suffix
-
- // Compute year, month, day if needed.
- if year < 0 && std&stdNeedDate != 0 {
- year, month, day, _ = absDate(abs, true)
- }
-
- // Compute hour, minute, second if needed.
- if hour < 0 && std&stdNeedClock != 0 {
- hour, min, sec = absClock(abs)
- }
-
- switch std & stdMask {
- case stdYear:
- y := year
- if y < 0 {
- y = -y
- }
- b = appendUint(b, uint(y%100), '0')
- case stdLongYear:
- // Pad year to at least 4 digits.
- y := year
- switch {
- case year <= -1000:
- b = append(b, '-')
- y = -y
- case year <= -100:
- b = append(b, "-0"...)
- y = -y
- case year <= -10:
- b = append(b, "-00"...)
- y = -y
- case year < 0:
- b = append(b, "-000"...)
- y = -y
- case year < 10:
- b = append(b, "000"...)
- case year < 100:
- b = append(b, "00"...)
- case year < 1000:
- b = append(b, '0')
- }
- b = appendUint(b, uint(y), 0)
- case stdMonth:
- b = append(b, month.String()[:3]...)
- case stdLongMonth:
- m := month.String()
- b = append(b, m...)
- case stdNumMonth:
- b = appendUint(b, uint(month), 0)
- case stdZeroMonth:
- b = appendUint(b, uint(month), '0')
- case stdWeekDay:
- b = append(b, absWeekday(abs).String()[:3]...)
- case stdLongWeekDay:
- s := absWeekday(abs).String()
- b = append(b, s...)
- case stdDay:
- b = appendUint(b, uint(day), 0)
- case stdUnderDay:
- b = appendUint(b, uint(day), ' ')
- case stdZeroDay:
- b = appendUint(b, uint(day), '0')
- case stdHour:
- b = appendUint(b, uint(hour), '0')
- case stdHour12:
- // Noon is 12PM, midnight is 12AM.
- hr := hour % 12
- if hr == 0 {
- hr = 12
- }
- b = appendUint(b, uint(hr), 0)
- case stdZeroHour12:
- // Noon is 12PM, midnight is 12AM.
- hr := hour % 12
- if hr == 0 {
- hr = 12
- }
- b = appendUint(b, uint(hr), '0')
- case stdMinute:
- b = appendUint(b, uint(min), 0)
- case stdZeroMinute:
- b = appendUint(b, uint(min), '0')
- case stdSecond:
- b = appendUint(b, uint(sec), 0)
- case stdZeroSecond:
- b = appendUint(b, uint(sec), '0')
- case stdPM:
- if hour >= 12 {
- b = append(b, "PM"...)
- } else {
- b = append(b, "AM"...)
- }
- case stdpm:
- if hour >= 12 {
- b = append(b, "pm"...)
- } else {
- b = append(b, "am"...)
- }
- case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
- // Ugly special case. We cheat and take the "Z" variants
- // to mean "the time zone as formatted for ISO 8601".
- if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ || std == stdISO8601SecondsTZ || std == stdISO8601ColonSecondsTZ) {
- b = append(b, 'Z')
- break
- }
- zone := offset / 60 // convert to minutes
- absoffset := offset
- if zone < 0 {
- b = append(b, '-')
- zone = -zone
- absoffset = -absoffset
- } else {
- b = append(b, '+')
- }
- b = appendUint(b, uint(zone/60), '0')
- if std == stdISO8601ColonTZ || std == stdNumColonTZ {
- b = append(b, ':')
- }
- b = appendUint(b, uint(zone%60), '0')
-
- // append seconds if appropriate
- if std == stdISO8601SecondsTZ || std == stdNumSecondsTz || std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
- if std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
- b = append(b, ':')
- }
- b = appendUint(b, uint(absoffset%60), '0')
- }
-
- case stdTZ:
- if name != "" {
- b = append(b, name...)
- break
- }
- // No time zone known for this time, but we must print one.
- // Use the -0700 format.
- zone := offset / 60 // convert to minutes
- if zone < 0 {
- b = append(b, '-')
- zone = -zone
- } else {
- b = append(b, '+')
- }
- b = appendUint(b, uint(zone/60), '0')
- b = appendUint(b, uint(zone%60), '0')
- case stdFracSecond0, stdFracSecond9:
- b = formatNano(b, uint(t.Nanosecond()), std>>stdArgShift, std&stdMask == stdFracSecond9)
- }
- }
- return string(b)
-}
-
-var errBad = errors.New("bad value for field") // placeholder not passed to user
-
-// ParseError describes a problem parsing a time string.
-type ParseError struct {
- Layout string
- Value string
- LayoutElem string
- ValueElem string
- Message string
-}
-
-func quote(s string) string {
- return "\"" + s + "\""
-}
-
-// Error returns the string representation of a ParseError.
-func (e *ParseError) Error() string {
- if e.Message == "" {
- return "parsing time " +
- quote(e.Value) + " as " +
- quote(e.Layout) + ": cannot parse " +
- quote(e.ValueElem) + " as " +
- quote(e.LayoutElem)
- }
- return "parsing time " +
- quote(e.Value) + e.Message
-}
-
-// isDigit returns true if s[i] is a decimal digit, false if not or
-// if s[i] is out of range.
-func isDigit(s string, i int) bool {
- if len(s) <= i {
- return false
- }
- c := s[i]
- return '0' <= c && c <= '9'
-}
-
-// getnum parses s[0:1] or s[0:2] (fixed forces the latter)
-// as a decimal integer and returns the integer and the
-// remainder of the string.
-func getnum(s string, fixed bool) (int, string, error) {
- if !isDigit(s, 0) {
- return 0, s, errBad
- }
- if !isDigit(s, 1) {
- if fixed {
- return 0, s, errBad
- }
- return int(s[0] - '0'), s[1:], nil
- }
- return int(s[0]-'0')*10 + int(s[1]-'0'), s[2:], nil
-}
-
-func cutspace(s string) string {
- for len(s) > 0 && s[0] == ' ' {
- s = s[1:]
- }
- return s
-}
-
-// skip removes the given prefix from value,
-// treating runs of space characters as equivalent.
-func skip(value, prefix string) (string, error) {
- for len(prefix) > 0 {
- if prefix[0] == ' ' {
- if len(value) > 0 && value[0] != ' ' {
- return value, errBad
- }
- prefix = cutspace(prefix)
- value = cutspace(value)
- continue
- }
- if len(value) == 0 || value[0] != prefix[0] {
- return value, errBad
- }
- prefix = prefix[1:]
- value = value[1:]
- }
- return value, nil
-}
-
-// Parse parses a formatted string and returns the time value it represents.
-// The layout defines the format by showing how the reference time,
-// Mon Jan 2 15:04:05 -0700 MST 2006
-// would be interpreted if it were the value; it serves as an example of
-// the input format. The same interpretation will then be made to the
-// input string.
-// Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard
-// and convenient representations of the reference time. For more information
-// about the formats and the definition of the reference time, see the
-// documentation for ANSIC and the other constants defined by this package.
-//
-// Elements omitted from the value are assumed to be zero or, when
-// zero is impossible, one, so parsing "3:04pm" returns the time
-// corresponding to Jan 1, year 0, 15:04:00 UTC (note that because the year is
-// 0, this time is before the zero Time).
-// Years must be in the range 0000..9999. The day of the week is checked
-// for syntax but it is otherwise ignored.
-//
-// In the absence of a time zone indicator, Parse returns a time in UTC.
-//
-// When parsing a time with a zone offset like -0700, if the offset corresponds
-// to a time zone used by the current location (Local), then Parse uses that
-// location and zone in the returned time. Otherwise it records the time as
-// being in a fabricated location with time fixed at the given zone offset.
-//
-// When parsing a time with a zone abbreviation like MST, if the zone abbreviation
-// has a defined offset in the current location, then that offset is used.
-// The zone abbreviation "UTC" is recognized as UTC regardless of location.
-// If the zone abbreviation is unknown, Parse records the time as being
-// in a fabricated location with the given zone abbreviation and a zero offset.
-// This choice means that such a time can be parse and reformatted with the
-// same layout losslessly, but the exact instant used in the representation will
-// differ by the actual zone offset. To avoid such problems, prefer time layouts
-// that use a numeric zone offset, or use ParseInLocation.
-func Parse(layout, value string) (Time, error) {
- return parse(layout, value, UTC, Local)
-}
-
-// ParseInLocation is like Parse but differs in two important ways.
-// First, in the absence of time zone information, Parse interprets a time as UTC;
-// ParseInLocation interprets the time as in the given location.
-// Second, when given a zone offset or abbreviation, Parse tries to match it
-// against the Local location; ParseInLocation uses the given location.
-func ParseInLocation(layout, value string, loc *Location) (Time, error) {
- return parse(layout, value, loc, loc)
-}
-
-func parse(layout, value string, defaultLocation, local *Location) (Time, error) {
- alayout, avalue := layout, value
- rangeErrString := "" // set if a value is out of range
- amSet := false // do we need to subtract 12 from the hour for midnight?
- pmSet := false // do we need to add 12 to the hour?
-
- // Time being constructed.
- var (
- year int
- month int = 1 // January
- day int = 1
- hour int
- min int
- sec int
- nsec int
- z *Location
- zoneOffset int = -1
- zoneName string
- )
-
- // Each iteration processes one std value.
- for {
- var err error
- prefix, std, suffix := nextStdChunk(layout)
- stdstr := layout[len(prefix) : len(layout)-len(suffix)]
- value, err = skip(value, prefix)
- if err != nil {
- return Time{}, &ParseError{alayout, avalue, prefix, value, ""}
- }
- if std == 0 {
- if len(value) != 0 {
- return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
- }
- break
- }
- layout = suffix
- var p string
- switch std & stdMask {
- case stdYear:
- if len(value) < 2 {
- err = errBad
- break
- }
- p, value = value[0:2], value[2:]
- year, err = atoi(p)
- if year >= 69 { // Unix time starts Dec 31 1969 in some time zones
- year += 1900
- } else {
- year += 2000
- }
- case stdLongYear:
- if len(value) < 4 || !isDigit(value, 0) {
- err = errBad
- break
- }
- p, value = value[0:4], value[4:]
- year, err = atoi(p)
- case stdMonth:
- month, value, err = lookup(shortMonthNames, value)
- case stdLongMonth:
- month, value, err = lookup(longMonthNames, value)
- case stdNumMonth, stdZeroMonth:
- month, value, err = getnum(value, std == stdZeroMonth)
- if month <= 0 || 12 < month {
- rangeErrString = "month"
- }
- case stdWeekDay:
- // Ignore weekday except for error checking.
- _, value, err = lookup(shortDayNames, value)
- case stdLongWeekDay:
- _, value, err = lookup(longDayNames, value)
- case stdDay, stdUnderDay, stdZeroDay:
- if std == stdUnderDay && len(value) > 0 && value[0] == ' ' {
- value = value[1:]
- }
- day, value, err = getnum(value, std == stdZeroDay)
- if day < 0 || 31 < day {
- rangeErrString = "day"
- }
- case stdHour:
- hour, value, err = getnum(value, false)
- if hour < 0 || 24 <= hour {
- rangeErrString = "hour"
- }
- case stdHour12, stdZeroHour12:
- hour, value, err = getnum(value, std == stdZeroHour12)
- if hour < 0 || 12 < hour {
- rangeErrString = "hour"
- }
- case stdMinute, stdZeroMinute:
- min, value, err = getnum(value, std == stdZeroMinute)
- if min < 0 || 60 <= min {
- rangeErrString = "minute"
- }
- case stdSecond, stdZeroSecond:
- sec, value, err = getnum(value, std == stdZeroSecond)
- if sec < 0 || 60 <= sec {
- rangeErrString = "second"
- }
- // Special case: do we have a fractional second but no
- // fractional second in the format?
- if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
- _, std, _ = nextStdChunk(layout)
- std &= stdMask
- if std == stdFracSecond0 || std == stdFracSecond9 {
- // Fractional second in the layout; proceed normally
- break
- }
- // No fractional second in the layout but we have one in the input.
- n := 2
- for ; n < len(value) && isDigit(value, n); n++ {
- }
- nsec, rangeErrString, err = parseNanoseconds(value, n)
- value = value[n:]
- }
- case stdPM:
- if len(value) < 2 {
- err = errBad
- break
- }
- p, value = value[0:2], value[2:]
- switch p {
- case "PM":
- pmSet = true
- case "AM":
- amSet = true
- default:
- err = errBad
- }
- case stdpm:
- if len(value) < 2 {
- err = errBad
- break
- }
- p, value = value[0:2], value[2:]
- switch p {
- case "pm":
- pmSet = true
- case "am":
- amSet = true
- default:
- err = errBad
- }
- case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
- if (std == stdISO8601TZ || std == stdISO8601ColonTZ) && len(value) >= 1 && value[0] == 'Z' {
- value = value[1:]
- z = UTC
- break
- }
- var sign, hour, min, seconds string
- if std == stdISO8601ColonTZ || std == stdNumColonTZ {
- if len(value) < 6 {
- err = errBad
- break
- }
- if value[3] != ':' {
- err = errBad
- break
- }
- sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], "00", value[6:]
- } else if std == stdNumShortTZ {
- if len(value) < 3 {
- err = errBad
- break
- }
- sign, hour, min, seconds, value = value[0:1], value[1:3], "00", "00", value[3:]
- } else if std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
- if len(value) < 9 {
- err = errBad
- break
- }
- if value[3] != ':' || value[6] != ':' {
- err = errBad
- break
- }
- sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], value[7:9], value[9:]
- } else if std == stdISO8601SecondsTZ || std == stdNumSecondsTz {
- if len(value) < 7 {
- err = errBad
- break
- }
- sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], value[5:7], value[7:]
- } else {
- if len(value) < 5 {
- err = errBad
- break
- }
- sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], "00", value[5:]
- }
- var hr, mm, ss int
- hr, err = atoi(hour)
- if err == nil {
- mm, err = atoi(min)
- }
- if err == nil {
- ss, err = atoi(seconds)
- }
- zoneOffset = (hr*60+mm)*60 + ss // offset is in seconds
- switch sign[0] {
- case '+':
- case '-':
- zoneOffset = -zoneOffset
- default:
- err = errBad
- }
- case stdTZ:
- // Does it look like a time zone?
- if len(value) >= 3 && value[0:3] == "UTC" {
- z = UTC
- value = value[3:]
- break
- }
- n, ok := parseTimeZone(value)
- if !ok {
- err = errBad
- break
- }
- zoneName, value = value[:n], value[n:]
-
- case stdFracSecond0:
- // stdFracSecond0 requires the exact number of digits as specified in
- // the layout.
- ndigit := 1 + (std >> stdArgShift)
- if len(value) < ndigit {
- err = errBad
- break
- }
- nsec, rangeErrString, err = parseNanoseconds(value, ndigit)
- value = value[ndigit:]
-
- case stdFracSecond9:
- if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] {
- // Fractional second omitted.
- break
- }
- // Take any number of digits, even more than asked for,
- // because it is what the stdSecond case would do.
- i := 0
- for i < 9 && i+1 < len(value) && '0' <= value[i+1] && value[i+1] <= '9' {
- i++
- }
- nsec, rangeErrString, err = parseNanoseconds(value, 1+i)
- value = value[1+i:]
- }
- if rangeErrString != "" {
- return Time{}, &ParseError{alayout, avalue, stdstr, value, ": " + rangeErrString + " out of range"}
- }
- if err != nil {
- return Time{}, &ParseError{alayout, avalue, stdstr, value, ""}
- }
- }
- if pmSet && hour < 12 {
- hour += 12
- } else if amSet && hour == 12 {
- hour = 0
- }
-
- if z != nil {
- return Date(year, Month(month), day, hour, min, sec, nsec, z), nil
- }
-
- if zoneOffset != -1 {
- t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
- t.sec -= int64(zoneOffset)
-
- // Look for local zone with the given offset.
- // If that zone was in effect at the given time, use it.
- name, offset, _, _, _ := local.lookup(t.sec + internalToUnix)
- if offset == zoneOffset && (zoneName == "" || name == zoneName) {
- t.loc = local
- return t, nil
- }
-
- // Otherwise create fake zone to record offset.
- t.loc = FixedZone(zoneName, zoneOffset)
- return t, nil
- }
-
- if zoneName != "" {
- t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
- // Look for local zone with the given offset.
- // If that zone was in effect at the given time, use it.
- offset, _, ok := local.lookupName(zoneName, t.sec+internalToUnix)
- if ok {
- t.sec -= int64(offset)
- t.loc = local
- return t, nil
- }
-
- // Otherwise, create fake zone with unknown offset.
- if len(zoneName) > 3 && zoneName[:3] == "GMT" {
- offset, _ = atoi(zoneName[3:]) // Guaranteed OK by parseGMT.
- offset *= 3600
- }
- t.loc = FixedZone(zoneName, offset)
- return t, nil
- }
-
- // Otherwise, fall back to default.
- return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil
-}
-
-// parseTimeZone parses a time zone string and returns its length. Time zones
-// are human-generated and unpredictable. We can't do precise error checking.
-// On the other hand, for a correct parse there must be a time zone at the
-// beginning of the string, so it's almost always true that there's one
-// there. We look at the beginning of the string for a run of upper-case letters.
-// If there are more than 5, it's an error.
-// If there are 4 or 5 and the last is a T, it's a time zone.
-// If there are 3, it's a time zone.
-// Otherwise, other than special cases, it's not a time zone.
-// GMT is special because it can have an hour offset.
-func parseTimeZone(value string) (length int, ok bool) {
- if len(value) < 3 {
- return 0, false
- }
- // Special case 1: ChST and MeST are the only zones with a lower-case letter.
- if len(value) >= 4 && (value[:4] == "ChST" || value[:4] == "MeST") {
- return 4, true
- }
- // Special case 2: GMT may have an hour offset; treat it specially.
- if value[:3] == "GMT" {
- length = parseGMT(value)
- return length, true
- }
- // How many upper-case letters are there? Need at least three, at most five.
- var nUpper int
- for nUpper = 0; nUpper < 6; nUpper++ {
- if nUpper >= len(value) {
- break
- }
- if c := value[nUpper]; c < 'A' || 'Z' < c {
- break
- }
- }
- switch nUpper {
- case 0, 1, 2, 6:
- return 0, false
- case 5: // Must end in T to match.
- if value[4] == 'T' {
- return 5, true
- }
- case 4: // Must end in T to match.
- if value[3] == 'T' {
- return 4, true
- }
- case 3:
- return 3, true
- }
- return 0, false
-}
-
-// parseGMT parses a GMT time zone. The input string is known to start "GMT".
-// The function checks whether that is followed by a sign and a number in the
-// range -14 through 12 excluding zero.
-func parseGMT(value string) int {
- value = value[3:]
- if len(value) == 0 {
- return 3
- }
- sign := value[0]
- if sign != '-' && sign != '+' {
- return 3
- }
- x, rem, err := leadingInt(value[1:])
- if err != nil {
- return 3
- }
- if sign == '-' {
- x = -x
- }
- if x == 0 || x < -14 || 12 < x {
- return 3
- }
- return 3 + len(value) - len(rem)
-}
-
-func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
- if value[0] != '.' {
- err = errBad
- return
- }
- if ns, err = atoi(value[1:nbytes]); err != nil {
- return
- }
- if ns < 0 || 1e9 <= ns {
- rangeErrString = "fractional second"
- return
- }
- // We need nanoseconds, which means scaling by the number
- // of missing digits in the format, maximum length 10. If it's
- // longer than 10, we won't scale.
- scaleDigits := 10 - nbytes
- for i := 0; i < scaleDigits; i++ {
- ns *= 10
- }
- return
-}
-
-var errLeadingInt = errors.New("time: bad [0-9]*") // never printed
-
-// leadingInt consumes the leading [0-9]* from s.
-func leadingInt(s string) (x int64, rem string, err error) {
- i := 0
- for ; i < len(s); i++ {
- c := s[i]
- if c < '0' || c > '9' {
- break
- }
- if x >= (1<<63-10)/10 {
- // overflow
- return 0, "", errLeadingInt
- }
- x = x*10 + int64(c) - '0'
- }
- return x, s[i:], nil
-}
-
-var unitMap = map[string]float64{
- "ns": float64(Nanosecond),
- "us": float64(Microsecond),
- "µs": float64(Microsecond), // U+00B5 = micro symbol
- "μs": float64(Microsecond), // U+03BC = Greek letter mu
- "ms": float64(Millisecond),
- "s": float64(Second),
- "m": float64(Minute),
- "h": float64(Hour),
-}
-
-// ParseDuration parses a duration string.
-// A duration string is a possibly signed sequence of
-// decimal numbers, each with optional fraction and a unit suffix,
-// such as "300ms", "-1.5h" or "2h45m".
-// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
-func ParseDuration(s string) (Duration, error) {
- // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+
- orig := s
- f := float64(0)
- neg := false
-
- // Consume [-+]?
- if s != "" {
- c := s[0]
- if c == '-' || c == '+' {
- neg = c == '-'
- s = s[1:]
- }
- }
- // Special case: if all that is left is "0", this is zero.
- if s == "0" {
- return 0, nil
- }
- if s == "" {
- return 0, errors.New("time: invalid duration " + orig)
- }
- for s != "" {
- g := float64(0) // this element of the sequence
-
- var x int64
- var err error
-
- // The next character must be [0-9.]
- if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) {
- return 0, errors.New("time: invalid duration " + orig)
- }
- // Consume [0-9]*
- pl := len(s)
- x, s, err = leadingInt(s)
- if err != nil {
- return 0, errors.New("time: invalid duration " + orig)
- }
- g = float64(x)
- pre := pl != len(s) // whether we consumed anything before a period
-
- // Consume (\.[0-9]*)?
- post := false
- if s != "" && s[0] == '.' {
- s = s[1:]
- pl := len(s)
- x, s, err = leadingInt(s)
- if err != nil {
- return 0, errors.New("time: invalid duration " + orig)
- }
- scale := 1.0
- for n := pl - len(s); n > 0; n-- {
- scale *= 10
- }
- g += float64(x) / scale
- post = pl != len(s)
- }
- if !pre && !post {
- // no digits (e.g. ".s" or "-.s")
- return 0, errors.New("time: invalid duration " + orig)
- }
-
- // Consume unit.
- i := 0
- for ; i < len(s); i++ {
- c := s[i]
- if c == '.' || ('0' <= c && c <= '9') {
- break
- }
- }
- if i == 0 {
- return 0, errors.New("time: missing unit in duration " + orig)
- }
- u := s[:i]
- s = s[i:]
- unit, ok := unitMap[u]
- if !ok {
- return 0, errors.New("time: unknown unit " + u + " in duration " + orig)
- }
-
- f += g * unit
- }
-
- if neg {
- f = -f
- }
- if f < float64(-1<<63) || f > float64(1<<63-1) {
- return 0, errors.New("time: overflow parsing duration")
- }
- return Duration(f), nil
-}
diff --git a/src/pkg/time/format_test.go b/src/pkg/time/format_test.go
deleted file mode 100644
index 46a598155..000000000
--- a/src/pkg/time/format_test.go
+++ /dev/null
@@ -1,517 +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_test
-
-import (
- "fmt"
- "strconv"
- "strings"
- "testing"
- "testing/quick"
- . "time"
-)
-
-type TimeFormatTest struct {
- time Time
- formattedValue string
-}
-
-var rfc3339Formats = []TimeFormatTest{
- {Date(2008, 9, 17, 20, 4, 26, 0, UTC), "2008-09-17T20:04:26Z"},
- {Date(1994, 9, 17, 20, 4, 26, 0, FixedZone("EST", -18000)), "1994-09-17T20:04:26-05:00"},
- {Date(2000, 12, 26, 1, 15, 6, 0, FixedZone("OTO", 15600)), "2000-12-26T01:15:06+04:20"},
-}
-
-func TestRFC3339Conversion(t *testing.T) {
- for _, f := range rfc3339Formats {
- if f.time.Format(RFC3339) != f.formattedValue {
- t.Error("RFC3339:")
- t.Errorf(" want=%+v", f.formattedValue)
- t.Errorf(" have=%+v", f.time.Format(RFC3339))
- }
- }
-}
-
-type FormatTest struct {
- name string
- format string
- result string
-}
-
-var formatTests = []FormatTest{
- {"ANSIC", ANSIC, "Wed Feb 4 21:00:57 2009"},
- {"UnixDate", UnixDate, "Wed Feb 4 21:00:57 PST 2009"},
- {"RubyDate", RubyDate, "Wed Feb 04 21:00:57 -0800 2009"},
- {"RFC822", RFC822, "04 Feb 09 21:00 PST"},
- {"RFC850", RFC850, "Wednesday, 04-Feb-09 21:00:57 PST"},
- {"RFC1123", RFC1123, "Wed, 04 Feb 2009 21:00:57 PST"},
- {"RFC1123Z", RFC1123Z, "Wed, 04 Feb 2009 21:00:57 -0800"},
- {"RFC3339", RFC3339, "2009-02-04T21:00:57-08:00"},
- {"RFC3339Nano", RFC3339Nano, "2009-02-04T21:00:57.0123456-08:00"},
- {"Kitchen", Kitchen, "9:00PM"},
- {"am/pm", "3pm", "9pm"},
- {"AM/PM", "3PM", "9PM"},
- {"two-digit year", "06 01 02", "09 02 04"},
- // Three-letter months and days must not be followed by lower-case letter.
- {"Janet", "Hi Janet, the Month is January", "Hi Janet, the Month is February"},
- // Time stamps, Fractional seconds.
- {"Stamp", Stamp, "Feb 4 21:00:57"},
- {"StampMilli", StampMilli, "Feb 4 21:00:57.012"},
- {"StampMicro", StampMicro, "Feb 4 21:00:57.012345"},
- {"StampNano", StampNano, "Feb 4 21:00:57.012345600"},
-}
-
-func TestFormat(t *testing.T) {
- // The numeric time represents Thu Feb 4 21:00:57.012345600 PST 2010
- time := Unix(0, 1233810057012345600)
- for _, test := range formatTests {
- result := time.Format(test.format)
- if result != test.result {
- t.Errorf("%s expected %q got %q", test.name, test.result, result)
- }
- }
-}
-
-func TestFormatShortYear(t *testing.T) {
- years := []int{
- -100001, -100000, -99999,
- -10001, -10000, -9999,
- -1001, -1000, -999,
- -101, -100, -99,
- -11, -10, -9,
- -1, 0, 1,
- 9, 10, 11,
- 99, 100, 101,
- 999, 1000, 1001,
- 9999, 10000, 10001,
- 99999, 100000, 100001,
- }
-
- for _, y := range years {
- time := Date(y, January, 1, 0, 0, 0, 0, UTC)
- result := time.Format("2006.01.02")
- var want string
- if y < 0 {
- // The 4 in %04d counts the - sign, so print -y instead
- // and introduce our own - sign.
- want = fmt.Sprintf("-%04d.%02d.%02d", -y, 1, 1)
- } else {
- want = fmt.Sprintf("%04d.%02d.%02d", y, 1, 1)
- }
- if result != want {
- t.Errorf("(jan 1 %d).Format(\"2006.01.02\") = %q, want %q", y, result, want)
- }
- }
-}
-
-type ParseTest struct {
- name string
- format string
- value string
- hasTZ bool // contains a time zone
- hasWD bool // contains a weekday
- yearSign int // sign of year, -1 indicates the year is not present in the format
- fracDigits int // number of digits of fractional second
-}
-
-var parseTests = []ParseTest{
- {"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true, 1, 0},
- {"UnixDate", UnixDate, "Thu Feb 4 21:00:57 PST 2010", true, true, 1, 0},
- {"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0800 2010", true, true, 1, 0},
- {"RFC850", RFC850, "Thursday, 04-Feb-10 21:00:57 PST", true, true, 1, 0},
- {"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57 PST", true, true, 1, 0},
- {"RFC1123", RFC1123, "Thu, 04 Feb 2010 22:00:57 PDT", true, true, 1, 0},
- {"RFC1123Z", RFC1123Z, "Thu, 04 Feb 2010 21:00:57 -0800", true, true, 1, 0},
- {"RFC3339", RFC3339, "2010-02-04T21:00:57-08:00", true, false, 1, 0},
- {"custom: \"2006-01-02 15:04:05-07\"", "2006-01-02 15:04:05-07", "2010-02-04 21:00:57-08", true, false, 1, 0},
- // Optional fractional seconds.
- {"ANSIC", ANSIC, "Thu Feb 4 21:00:57.0 2010", false, true, 1, 1},
- {"UnixDate", UnixDate, "Thu Feb 4 21:00:57.01 PST 2010", true, true, 1, 2},
- {"RubyDate", RubyDate, "Thu Feb 04 21:00:57.012 -0800 2010", true, true, 1, 3},
- {"RFC850", RFC850, "Thursday, 04-Feb-10 21:00:57.0123 PST", true, true, 1, 4},
- {"RFC1123", RFC1123, "Thu, 04 Feb 2010 21:00:57.01234 PST", true, true, 1, 5},
- {"RFC1123Z", RFC1123Z, "Thu, 04 Feb 2010 21:00:57.01234 -0800", true, true, 1, 5},
- {"RFC3339", RFC3339, "2010-02-04T21:00:57.012345678-08:00", true, false, 1, 9},
- {"custom: \"2006-01-02 15:04:05\"", "2006-01-02 15:04:05", "2010-02-04 21:00:57.0", false, false, 1, 0},
- // Amount of white space should not matter.
- {"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true, 1, 0},
- {"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true, 1, 0},
- // Case should not matter
- {"ANSIC", ANSIC, "THU FEB 4 21:00:57 2010", false, true, 1, 0},
- {"ANSIC", ANSIC, "thu feb 4 21:00:57 2010", false, true, 1, 0},
- // Fractional seconds.
- {"millisecond", "Mon Jan _2 15:04:05.000 2006", "Thu Feb 4 21:00:57.012 2010", false, true, 1, 3},
- {"microsecond", "Mon Jan _2 15:04:05.000000 2006", "Thu Feb 4 21:00:57.012345 2010", false, true, 1, 6},
- {"nanosecond", "Mon Jan _2 15:04:05.000000000 2006", "Thu Feb 4 21:00:57.012345678 2010", false, true, 1, 9},
- // Leading zeros in other places should not be taken as fractional seconds.
- {"zero1", "2006.01.02.15.04.05.0", "2010.02.04.21.00.57.0", false, false, 1, 1},
- {"zero2", "2006.01.02.15.04.05.00", "2010.02.04.21.00.57.01", false, false, 1, 2},
- // Month and day names only match when not followed by a lower-case letter.
- {"Janet", "Hi Janet, the Month is January: Jan _2 15:04:05 2006", "Hi Janet, the Month is February: Feb 4 21:00:57 2010", false, true, 1, 0},
-
- // GMT with offset.
- {"GMT-8", UnixDate, "Fri Feb 5 05:00:57 GMT-8 2010", true, true, 1, 0},
-
- // Accept any number of fractional second digits (including none) for .999...
- // In Go 1, .999... was completely ignored in the format, meaning the first two
- // cases would succeed, but the next four would not. Go 1.1 accepts all six.
- {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
- {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0},
- {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
- {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4},
- {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
- {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9},
-
- // issue 4502.
- {"", StampNano, "Feb 4 21:00:57.012345678", false, false, -1, 9},
- {"", "Jan _2 15:04:05.999", "Feb 4 21:00:57.012300000", false, false, -1, 4},
- {"", "Jan _2 15:04:05.999", "Feb 4 21:00:57.012345678", false, false, -1, 9},
- {"", "Jan _2 15:04:05.999999999", "Feb 4 21:00:57.0123", false, false, -1, 4},
- {"", "Jan _2 15:04:05.999999999", "Feb 4 21:00:57.012345678", false, false, -1, 9},
-}
-
-func TestParse(t *testing.T) {
- for _, test := range parseTests {
- time, err := Parse(test.format, test.value)
- if err != nil {
- t.Errorf("%s error: %v", test.name, err)
- } else {
- checkTime(time, &test, t)
- }
- }
-}
-
-func TestParseInLocation(t *testing.T) {
- // Check that Parse (and ParseInLocation) understand that
- // Feb 01 AST (Arabia Standard Time) and Feb 01 AST (Atlantic Standard Time)
- // are in different time zones even though both are called AST
-
- baghdad, err := LoadLocation("Asia/Baghdad")
- if err != nil {
- t.Fatal(err)
- }
-
- t1, err := ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", baghdad)
- if err != nil {
- t.Fatal(err)
- }
- t2 := Date(2013, February, 1, 00, 00, 00, 0, baghdad)
- if t1 != t2 {
- t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad) = %v, want %v", t1, t2)
- }
- _, offset := t1.Zone()
- if offset != 3*60*60 {
- t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad).Zone = _, %d, want _, %d", offset, 3*60*60)
- }
-
- blancSablon, err := LoadLocation("America/Blanc-Sablon")
- if err != nil {
- t.Fatal(err)
- }
-
- t1, err = ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", blancSablon)
- if err != nil {
- t.Fatal(err)
- }
- t2 = Date(2013, February, 1, 00, 00, 00, 0, blancSablon)
- if t1 != t2 {
- t.Fatalf("ParseInLocation(Feb 01 2013 AST, Blanc-Sablon) = %v, want %v", t1, t2)
- }
- _, offset = t1.Zone()
- if offset != -4*60*60 {
- t.Fatalf("ParseInLocation(Feb 01 2013 AST, Blanc-Sablon).Zone = _, %d, want _, %d", offset, -4*60*60)
- }
-}
-
-func TestLoadLocationZipFile(t *testing.T) {
- ForceZipFileForTesting(true)
- defer ForceZipFileForTesting(false)
-
- _, err := LoadLocation("Australia/Sydney")
- if err != nil {
- t.Fatal(err)
- }
-}
-
-var rubyTests = []ParseTest{
- {"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0800 2010", true, true, 1, 0},
- // Ignore the time zone in the test. If it parses, it'll be OK.
- {"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0000 2010", false, true, 1, 0},
- {"RubyDate", RubyDate, "Thu Feb 04 21:00:57 +0000 2010", false, true, 1, 0},
- {"RubyDate", RubyDate, "Thu Feb 04 21:00:57 +1130 2010", false, true, 1, 0},
-}
-
-// Problematic time zone format needs special tests.
-func TestRubyParse(t *testing.T) {
- for _, test := range rubyTests {
- time, err := Parse(test.format, test.value)
- if err != nil {
- t.Errorf("%s error: %v", test.name, err)
- } else {
- checkTime(time, &test, t)
- }
- }
-}
-
-func checkTime(time Time, test *ParseTest, t *testing.T) {
- // The time should be Thu Feb 4 21:00:57 PST 2010
- if test.yearSign >= 0 && test.yearSign*time.Year() != 2010 {
- t.Errorf("%s: bad year: %d not %d", test.name, time.Year(), 2010)
- }
- if time.Month() != February {
- t.Errorf("%s: bad month: %s not %s", test.name, time.Month(), February)
- }
- if time.Day() != 4 {
- t.Errorf("%s: bad day: %d not %d", test.name, time.Day(), 4)
- }
- if time.Hour() != 21 {
- t.Errorf("%s: bad hour: %d not %d", test.name, time.Hour(), 21)
- }
- if time.Minute() != 0 {
- t.Errorf("%s: bad minute: %d not %d", test.name, time.Minute(), 0)
- }
- if time.Second() != 57 {
- t.Errorf("%s: bad second: %d not %d", test.name, time.Second(), 57)
- }
- // Nanoseconds must be checked against the precision of the input.
- nanosec, err := strconv.ParseUint("012345678"[:test.fracDigits]+"000000000"[:9-test.fracDigits], 10, 0)
- if err != nil {
- panic(err)
- }
- if time.Nanosecond() != int(nanosec) {
- t.Errorf("%s: bad nanosecond: %d not %d", test.name, time.Nanosecond(), nanosec)
- }
- name, offset := time.Zone()
- if test.hasTZ && offset != -28800 {
- t.Errorf("%s: bad tz offset: %s %d not %d", test.name, name, offset, -28800)
- }
- if test.hasWD && time.Weekday() != Thursday {
- t.Errorf("%s: bad weekday: %s not %s", test.name, time.Weekday(), Thursday)
- }
-}
-
-func TestFormatAndParse(t *testing.T) {
- const fmt = "Mon MST " + RFC3339 // all fields
- f := func(sec int64) bool {
- t1 := Unix(sec, 0)
- if t1.Year() < 1000 || t1.Year() > 9999 {
- // not required to work
- return true
- }
- t2, err := Parse(fmt, t1.Format(fmt))
- if err != nil {
- t.Errorf("error: %s", err)
- return false
- }
- if t1.Unix() != t2.Unix() || t1.Nanosecond() != t2.Nanosecond() {
- t.Errorf("FormatAndParse %d: %q(%d) %q(%d)", sec, t1, t1.Unix(), t2, t2.Unix())
- return false
- }
- return true
- }
- f32 := func(sec int32) bool { return f(int64(sec)) }
- cfg := &quick.Config{MaxCount: 10000}
-
- // Try a reasonable date first, then the huge ones.
- if err := quick.Check(f32, cfg); err != nil {
- t.Fatal(err)
- }
- if err := quick.Check(f, cfg); err != nil {
- t.Fatal(err)
- }
-}
-
-type ParseTimeZoneTest struct {
- value string
- length int
- ok bool
-}
-
-var parseTimeZoneTests = []ParseTimeZoneTest{
- {"gmt hi there", 0, false},
- {"GMT hi there", 3, true},
- {"GMT+12 hi there", 6, true},
- {"GMT+00 hi there", 3, true}, // 0 or 00 is not a legal offset.
- {"GMT-5 hi there", 5, true},
- {"GMT-51 hi there", 3, true},
- {"ChST hi there", 4, true},
- {"MeST hi there", 4, true},
- {"MSDx", 3, true},
- {"MSDY", 0, false}, // four letters must end in T.
- {"ESAST hi", 5, true},
- {"ESASTT hi", 0, false}, // run of upper-case letters too long.
- {"ESATY hi", 0, false}, // five letters must end in T.
-}
-
-func TestParseTimeZone(t *testing.T) {
- for _, test := range parseTimeZoneTests {
- length, ok := ParseTimeZone(test.value)
- if ok != test.ok {
- t.Errorf("expected %t for %q got %t", test.ok, test.value, ok)
- } else if length != test.length {
- t.Errorf("expected %d for %q got %d", test.length, test.value, length)
- }
- }
-}
-
-type ParseErrorTest struct {
- format string
- value string
- expect string // must appear within the error
-}
-
-var parseErrorTests = []ParseErrorTest{
- {ANSIC, "Feb 4 21:00:60 2010", "cannot parse"}, // cannot parse Feb as Mon
- {ANSIC, "Thu Feb 4 21:00:57 @2010", "cannot parse"},
- {ANSIC, "Thu Feb 4 21:00:60 2010", "second out of range"},
- {ANSIC, "Thu Feb 4 21:61:57 2010", "minute out of range"},
- {ANSIC, "Thu Feb 4 24:00:60 2010", "hour out of range"},
- {"Mon Jan _2 15:04:05.000 2006", "Thu Feb 4 23:00:59x01 2010", "cannot parse"},
- {"Mon Jan _2 15:04:05.000 2006", "Thu Feb 4 23:00:59.xxx 2010", "cannot parse"},
- {"Mon Jan _2 15:04:05.000 2006", "Thu Feb 4 23:00:59.-123 2010", "fractional second out of range"},
- // issue 4502. StampNano requires exactly 9 digits of precision.
- {StampNano, "Dec 7 11:22:01.000000", `cannot parse ".000000" as ".000000000"`},
- {StampNano, "Dec 7 11:22:01.0000000000", "extra text: 0"},
- // issue 4493. Helpful errors.
- {RFC3339, "2006-01-02T15:04:05Z07:00", `parsing time "2006-01-02T15:04:05Z07:00": extra text: 07:00`},
- {RFC3339, "2006-01-02T15:04_abc", `parsing time "2006-01-02T15:04_abc" as "2006-01-02T15:04:05Z07:00": cannot parse "_abc" as ":"`},
- {RFC3339, "2006-01-02T15:04:05_abc", `parsing time "2006-01-02T15:04:05_abc" as "2006-01-02T15:04:05Z07:00": cannot parse "_abc" as "Z07:00"`},
- {RFC3339, "2006-01-02T15:04:05Z_abc", `parsing time "2006-01-02T15:04:05Z_abc": extra text: _abc`},
-}
-
-func TestParseErrors(t *testing.T) {
- for _, test := range parseErrorTests {
- _, err := Parse(test.format, test.value)
- if err == nil {
- t.Errorf("expected error for %q %q", test.format, test.value)
- } else if strings.Index(err.Error(), test.expect) < 0 {
- t.Errorf("expected error with %q for %q %q; got %s", test.expect, test.format, test.value, err)
- }
- }
-}
-
-func TestNoonIs12PM(t *testing.T) {
- noon := Date(0, January, 1, 12, 0, 0, 0, UTC)
- const expect = "12:00PM"
- got := noon.Format("3:04PM")
- if got != expect {
- t.Errorf("got %q; expect %q", got, expect)
- }
- got = noon.Format("03:04PM")
- if got != expect {
- t.Errorf("got %q; expect %q", got, expect)
- }
-}
-
-func TestMidnightIs12AM(t *testing.T) {
- midnight := Date(0, January, 1, 0, 0, 0, 0, UTC)
- expect := "12:00AM"
- got := midnight.Format("3:04PM")
- if got != expect {
- t.Errorf("got %q; expect %q", got, expect)
- }
- got = midnight.Format("03:04PM")
- if got != expect {
- t.Errorf("got %q; expect %q", got, expect)
- }
-}
-
-func Test12PMIsNoon(t *testing.T) {
- noon, err := Parse("3:04PM", "12:00PM")
- if err != nil {
- t.Fatal("error parsing date:", err)
- }
- if noon.Hour() != 12 {
- t.Errorf("got %d; expect 12", noon.Hour())
- }
- noon, err = Parse("03:04PM", "12:00PM")
- if err != nil {
- t.Fatal("error parsing date:", err)
- }
- if noon.Hour() != 12 {
- t.Errorf("got %d; expect 12", noon.Hour())
- }
-}
-
-func Test12AMIsMidnight(t *testing.T) {
- midnight, err := Parse("3:04PM", "12:00AM")
- if err != nil {
- t.Fatal("error parsing date:", err)
- }
- if midnight.Hour() != 0 {
- t.Errorf("got %d; expect 0", midnight.Hour())
- }
- midnight, err = Parse("03:04PM", "12:00AM")
- if err != nil {
- t.Fatal("error parsing date:", err)
- }
- if midnight.Hour() != 0 {
- t.Errorf("got %d; expect 0", midnight.Hour())
- }
-}
-
-// Check that a time without a Zone still produces a (numeric) time zone
-// when formatted with MST as a requested zone.
-func TestMissingZone(t *testing.T) {
- time, err := Parse(RubyDate, "Thu Feb 02 16:10:03 -0500 2006")
- if err != nil {
- t.Fatal("error parsing date:", err)
- }
- expect := "Thu Feb 2 16:10:03 -0500 2006" // -0500 not EST
- str := time.Format(UnixDate) // uses MST as its time zone
- if str != expect {
- t.Errorf("got %s; expect %s", str, expect)
- }
-}
-
-func TestMinutesInTimeZone(t *testing.T) {
- time, err := Parse(RubyDate, "Mon Jan 02 15:04:05 +0123 2006")
- if err != nil {
- t.Fatal("error parsing date:", err)
- }
- expected := (1*60 + 23) * 60
- _, offset := time.Zone()
- if offset != expected {
- t.Errorf("ZoneOffset = %d, want %d", offset, expected)
- }
-}
-
-type SecondsTimeZoneOffsetTest struct {
- format string
- value string
- expectedoffset int
-}
-
-var secondsTimeZoneOffsetTests = []SecondsTimeZoneOffsetTest{
- {"2006-01-02T15:04:05-070000", "1871-01-01T05:33:02-003408", -(34*60 + 8)},
- {"2006-01-02T15:04:05-07:00:00", "1871-01-01T05:33:02-00:34:08", -(34*60 + 8)},
- {"2006-01-02T15:04:05-070000", "1871-01-01T05:33:02+003408", 34*60 + 8},
- {"2006-01-02T15:04:05-07:00:00", "1871-01-01T05:33:02+00:34:08", 34*60 + 8},
- {"2006-01-02T15:04:05Z070000", "1871-01-01T05:33:02-003408", -(34*60 + 8)},
- {"2006-01-02T15:04:05Z07:00:00", "1871-01-01T05:33:02+00:34:08", 34*60 + 8},
-}
-
-func TestParseSecondsInTimeZone(t *testing.T) {
- // should accept timezone offsets with seconds like: Zone America/New_York -4:56:02 - LMT 1883 Nov 18 12:03:58
- for _, test := range secondsTimeZoneOffsetTests {
- time, err := Parse(test.format, test.value)
- if err != nil {
- t.Fatal("error parsing date:", err)
- }
- _, offset := time.Zone()
- if offset != test.expectedoffset {
- t.Errorf("ZoneOffset = %d, want %d", offset, test.expectedoffset)
- }
- }
-}
-
-func TestFormatSecondsInTimeZone(t *testing.T) {
- d := Date(1871, 9, 17, 20, 4, 26, 0, FixedZone("LMT", -(34*60+8)))
- timestr := d.Format("2006-01-02T15:04:05Z070000")
- expected := "1871-09-17T20:04:26-003408"
- if timestr != expected {
- t.Errorf("Got %s, want %s", timestr, expected)
- }
-}
diff --git a/src/pkg/time/genzabbrs.go b/src/pkg/time/genzabbrs.go
deleted file mode 100644
index 7c637cb43..000000000
--- a/src/pkg/time/genzabbrs.go
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2013 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.
-
-// +build ignore
-
-//
-// usage:
-//
-// go run genzabbrs.go | gofmt > $GOROOT/src/pkg/time/zoneinfo_abbrs_windows.go
-//
-
-package main
-
-import (
- "encoding/xml"
- "io/ioutil"
- "log"
- "net/http"
- "os"
- "sort"
- "text/template"
- "time"
-)
-
-// getAbbrs finds timezone abbreviations (standard and daylight saving time)
-// for location l.
-func getAbbrs(l *time.Location) (st, dt string) {
- t := time.Date(time.Now().Year(), 0, 0, 0, 0, 0, 0, l)
- abbr1, off1 := t.Zone()
- for i := 0; i < 12; i++ {
- t = t.AddDate(0, 1, 0)
- abbr2, off2 := t.Zone()
- if abbr1 != abbr2 {
- if off2-off1 < 0 { // southern hemisphere
- abbr1, abbr2 = abbr2, abbr1
- }
- return abbr1, abbr2
- }
- }
- return abbr1, abbr1
-}
-
-type zone struct {
- WinName string
- UnixName string
- StTime string
- DSTime string
-}
-
-type zones []*zone
-
-func (zs zones) Len() int { return len(zs) }
-func (zs zones) Swap(i, j int) { zs[i], zs[j] = zs[j], zs[i] }
-func (zs zones) Less(i, j int) bool { return zs[i].UnixName < zs[j].UnixName }
-
-const wzURL = "http://unicode.org/cldr/data/common/supplemental/windowsZones.xml"
-
-type MapZone struct {
- Other string `xml:"other,attr"`
- Territory string `xml:"territory,attr"`
- Type string `xml:"type,attr"`
-}
-
-type SupplementalData struct {
- Zones []MapZone `xml:"windowsZones>mapTimezones>mapZone"`
-}
-
-func readWindowsZones() (zones, error) {
- r, err := http.Get(wzURL)
- if err != nil {
- return nil, err
- }
- defer r.Body.Close()
-
- data, err := ioutil.ReadAll(r.Body)
- if err != nil {
- return nil, err
- }
-
- var sd SupplementalData
- err = xml.Unmarshal(data, &sd)
- if err != nil {
- return nil, err
- }
- zs := make(zones, 0)
- for _, z := range sd.Zones {
- if z.Territory != "001" {
- // to avoid dups. I don't know why.
- continue
- }
- l, err := time.LoadLocation(z.Type)
- if err != nil {
- return nil, err
- }
- st, dt := getAbbrs(l)
- zs = append(zs, &zone{
- WinName: z.Other,
- UnixName: z.Type,
- StTime: st,
- DSTime: dt,
- })
- }
- return zs, nil
-}
-
-func main() {
- zs, err := readWindowsZones()
- if err != nil {
- log.Fatal(err)
- }
- sort.Sort(zs)
- var v = struct {
- URL string
- Zs zones
- }{
- wzURL,
- zs,
- }
- err = template.Must(template.New("prog").Parse(prog)).Execute(os.Stdout, v)
- if err != nil {
- log.Fatal(err)
- }
-}
-
-const prog = `
-// Copyright 2013 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.
-
-// generated by genzabbrs.go from
-// {{.URL}}
-
-package time
-
-type abbr struct {
- std string
- dst string
-}
-
-var abbrs = map[string]abbr{
-{{range .Zs}} "{{.WinName}}": {"{{.StTime}}", "{{.DSTime}}"}, // {{.UnixName}}
-{{end}}}
-
-`
diff --git a/src/pkg/time/internal_test.go b/src/pkg/time/internal_test.go
deleted file mode 100644
index 2243d3668..000000000
--- a/src/pkg/time/internal_test.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2011 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 (
- "errors"
- "runtime"
-)
-
-func init() {
- // force US/Pacific for time zone tests
- ForceUSPacificForTesting()
-}
-
-var Interrupt = interrupt
-var DaysIn = daysIn
-
-func empty(now int64, arg interface{}) {}
-
-// Test that a runtimeTimer with a duration so large it overflows
-// does not cause other timers to hang.
-//
-// This test has to be in internal_test.go since it fiddles with
-// unexported data structures.
-func CheckRuntimeTimerOverflow() error {
- // We manually create a runtimeTimer to bypass the overflow
- // detection logic in NewTimer: we're testing the underlying
- // runtime.addtimer function.
- r := &runtimeTimer{
- when: runtimeNano() + (1<<63 - 1),
- f: empty,
- arg: nil,
- }
- startTimer(r)
-
- timeout := 100 * Millisecond
- switch runtime.GOOS {
- // Allow more time for gobuilder to succeed.
- case "windows":
- timeout = Second
- case "plan9":
- // TODO(0intro): We don't know why it is needed.
- timeout = 3 * Second
- }
-
- // Start a goroutine that should send on t.C before the timeout.
- t := NewTimer(1)
-
- defer func() {
- // Subsequent tests won't work correctly if we don't stop the
- // overflow timer and kick the timer proc back into service.
- //
- // The timer proc is now sleeping and can only be awoken by
- // adding a timer to the *beginning* of the heap. We can't
- // wake it up by calling NewTimer since other tests may have
- // left timers running that should have expired before ours.
- // Instead we zero the overflow timer duration and start it
- // once more.
- stopTimer(r)
- t.Stop()
- r.when = 0
- startTimer(r)
- }()
-
- // Try to receive from t.C before the timeout. It will succeed
- // iff the previous sleep was able to finish. We're forced to
- // spin and yield after trying to receive since we can't start
- // any more timers (they might hang due to the same bug we're
- // now testing).
- stop := Now().Add(timeout)
- for {
- select {
- case <-t.C:
- return nil // It worked!
- default:
- if Now().After(stop) {
- return errors.New("runtime timer stuck: overflow in addtimer")
- }
- // Issue 6874. This test previously called runtime.Gosched to try to yield
- // to the goroutine servicing t, however the scheduler has a bias towards the
- // previously running goroutine in an idle system. Combined with high load due
- // to all CPUs busy running tests t's goroutine could be delayed beyond the
- // timeout window.
- //
- // Calling runtime.GC() reduces the worst case lantency for scheduling t by 20x
- // under the current Go 1.3 scheduler.
- runtime.GC()
- }
- }
-}
diff --git a/src/pkg/time/sleep.go b/src/pkg/time/sleep.go
deleted file mode 100644
index 6a03f417b..000000000
--- a/src/pkg/time/sleep.go
+++ /dev/null
@@ -1,122 +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
-
-// Sleep pauses the current goroutine for at least the duration d.
-// A negative or zero duration causes Sleep to return immediately.
-func Sleep(d Duration)
-
-// runtimeNano returns the current value of the runtime clock in nanoseconds.
-func runtimeNano() int64
-
-// Interface to timers implemented in package runtime.
-// Must be in sync with ../runtime/runtime.h:/^struct.Timer$
-type runtimeTimer struct {
- i int32
- when int64
- period int64
- f func(int64, interface{}) // NOTE: must not be closure
- arg interface{}
-}
-
-// when is a helper function for setting the 'when' field of a runtimeTimer.
-// It returns what the time will be, in nanoseconds, Duration d in the future.
-// If d is negative, it is ignored. If the returned value would be less than
-// zero because of an overflow, MaxInt64 is returned.
-func when(d Duration) int64 {
- if d <= 0 {
- return runtimeNano()
- }
- t := runtimeNano() + int64(d)
- if t < 0 {
- t = 1<<63 - 1 // math.MaxInt64
- }
- return t
-}
-
-func startTimer(*runtimeTimer)
-func stopTimer(*runtimeTimer) bool
-
-// The Timer type represents a single event.
-// When the Timer expires, the current time will be sent on C,
-// unless the Timer was created by AfterFunc.
-type Timer struct {
- C <-chan Time
- r runtimeTimer
-}
-
-// Stop prevents the Timer from firing.
-// It returns true if the call stops the timer, false if the timer has already
-// expired or been stopped.
-// Stop does not close the channel, to prevent a read from the channel succeeding
-// incorrectly.
-func (t *Timer) Stop() bool {
- return stopTimer(&t.r)
-}
-
-// NewTimer creates a new Timer that will send
-// the current time on its channel after at least duration d.
-func NewTimer(d Duration) *Timer {
- c := make(chan Time, 1)
- t := &Timer{
- C: c,
- r: runtimeTimer{
- when: when(d),
- f: sendTime,
- arg: c,
- },
- }
- startTimer(&t.r)
- return t
-}
-
-// Reset changes the timer to expire after duration d.
-// It returns true if the timer had been active, false if the timer had
-// expired or been stopped.
-func (t *Timer) Reset(d Duration) bool {
- w := when(d)
- active := stopTimer(&t.r)
- t.r.when = w
- startTimer(&t.r)
- return active
-}
-
-func sendTime(now int64, c interface{}) {
- // Non-blocking send of time on c.
- // Used in NewTimer, it cannot block anyway (buffer).
- // Used in NewTicker, dropping sends on the floor is
- // the desired behavior when the reader gets behind,
- // because the sends are periodic.
- select {
- case c.(chan Time) <- Now():
- default:
- }
-}
-
-// After waits for the duration to elapse and then sends the current time
-// on the returned channel.
-// It is equivalent to NewTimer(d).C.
-func After(d Duration) <-chan Time {
- return NewTimer(d).C
-}
-
-// AfterFunc waits for the duration to elapse and then calls f
-// in its own goroutine. It returns a Timer that can
-// be used to cancel the call using its Stop method.
-func AfterFunc(d Duration, f func()) *Timer {
- t := &Timer{
- r: runtimeTimer{
- when: when(d),
- f: goFunc,
- arg: f,
- },
- }
- startTimer(&t.r)
- return t
-}
-
-func goFunc(now int64, arg interface{}) {
- go arg.(func())()
-}
diff --git a/src/pkg/time/sleep_test.go b/src/pkg/time/sleep_test.go
deleted file mode 100644
index 03f8e732c..000000000
--- a/src/pkg/time/sleep_test.go
+++ /dev/null
@@ -1,393 +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_test
-
-import (
- "errors"
- "fmt"
- "runtime"
- "sort"
- "sync"
- "sync/atomic"
- "testing"
- . "time"
-)
-
-func TestSleep(t *testing.T) {
- const delay = 100 * Millisecond
- go func() {
- Sleep(delay / 2)
- Interrupt()
- }()
- start := Now()
- Sleep(delay)
- duration := Now().Sub(start)
- if duration < delay {
- t.Fatalf("Sleep(%s) slept for only %s", delay, duration)
- }
-}
-
-// Test the basic function calling behavior. Correct queueing
-// behavior is tested elsewhere, since After and AfterFunc share
-// the same code.
-func TestAfterFunc(t *testing.T) {
- i := 10
- c := make(chan bool)
- var f func()
- f = func() {
- i--
- if i >= 0 {
- AfterFunc(0, f)
- Sleep(1 * Second)
- } else {
- c <- true
- }
- }
-
- AfterFunc(0, f)
- <-c
-}
-
-func TestAfterStress(t *testing.T) {
- stop := uint32(0)
- go func() {
- for atomic.LoadUint32(&stop) == 0 {
- runtime.GC()
- // Yield so that the OS can wake up the timer thread,
- // so that it can generate channel sends for the main goroutine,
- // which will eventually set stop = 1 for us.
- Sleep(Nanosecond)
- }
- }()
- ticker := NewTicker(1)
- for i := 0; i < 100; i++ {
- <-ticker.C
- }
- ticker.Stop()
- atomic.StoreUint32(&stop, 1)
-}
-
-func benchmark(b *testing.B, bench func(n int)) {
- garbage := make([]*Timer, 1<<17)
- for i := 0; i < len(garbage); i++ {
- garbage[i] = AfterFunc(Hour, nil)
- }
- b.ResetTimer()
-
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- bench(1000)
- }
- })
-
- b.StopTimer()
- for i := 0; i < len(garbage); i++ {
- garbage[i].Stop()
- }
-}
-
-func BenchmarkAfterFunc(b *testing.B) {
- benchmark(b, func(n int) {
- c := make(chan bool)
- var f func()
- f = func() {
- n--
- if n >= 0 {
- AfterFunc(0, f)
- } else {
- c <- true
- }
- }
-
- AfterFunc(0, f)
- <-c
- })
-}
-
-func BenchmarkAfter(b *testing.B) {
- benchmark(b, func(n int) {
- for i := 0; i < n; i++ {
- <-After(1)
- }
- })
-}
-
-func BenchmarkStop(b *testing.B) {
- benchmark(b, func(n int) {
- for i := 0; i < n; i++ {
- NewTimer(1 * Second).Stop()
- }
- })
-}
-
-func BenchmarkSimultaneousAfterFunc(b *testing.B) {
- benchmark(b, func(n int) {
- var wg sync.WaitGroup
- wg.Add(n)
- for i := 0; i < n; i++ {
- AfterFunc(0, wg.Done)
- }
- wg.Wait()
- })
-}
-
-func BenchmarkStartStop(b *testing.B) {
- benchmark(b, func(n int) {
- timers := make([]*Timer, n)
- for i := 0; i < n; i++ {
- timers[i] = AfterFunc(Hour, nil)
- }
-
- for i := 0; i < n; i++ {
- timers[i].Stop()
- }
- })
-}
-
-func TestAfter(t *testing.T) {
- const delay = 100 * Millisecond
- start := Now()
- end := <-After(delay)
- if duration := Now().Sub(start); duration < delay {
- t.Fatalf("After(%s) slept for only %d ns", delay, duration)
- }
- if min := start.Add(delay); end.Before(min) {
- t.Fatalf("After(%s) expect >= %s, got %s", delay, min, end)
- }
-}
-
-func TestAfterTick(t *testing.T) {
- const Count = 10
- Delta := 100 * Millisecond
- if testing.Short() {
- Delta = 10 * Millisecond
- }
- t0 := Now()
- for i := 0; i < Count; i++ {
- <-After(Delta)
- }
- t1 := Now()
- d := t1.Sub(t0)
- target := Delta * Count
- if d < target*9/10 {
- t.Fatalf("%d ticks of %s too fast: took %s, expected %s", Count, Delta, d, target)
- }
- if !testing.Short() && d > target*30/10 {
- t.Fatalf("%d ticks of %s too slow: took %s, expected %s", Count, Delta, d, target)
- }
-}
-
-func TestAfterStop(t *testing.T) {
- AfterFunc(100*Millisecond, func() {})
- t0 := NewTimer(50 * Millisecond)
- c1 := make(chan bool, 1)
- t1 := AfterFunc(150*Millisecond, func() { c1 <- true })
- c2 := After(200 * Millisecond)
- if !t0.Stop() {
- t.Fatalf("failed to stop event 0")
- }
- if !t1.Stop() {
- t.Fatalf("failed to stop event 1")
- }
- <-c2
- select {
- case <-t0.C:
- t.Fatalf("event 0 was not stopped")
- case <-c1:
- t.Fatalf("event 1 was not stopped")
- default:
- }
- if t1.Stop() {
- t.Fatalf("Stop returned true twice")
- }
-}
-
-func TestAfterQueuing(t *testing.T) {
- // This test flakes out on some systems,
- // so we'll try it a few times before declaring it a failure.
- const attempts = 3
- err := errors.New("!=nil")
- for i := 0; i < attempts && err != nil; i++ {
- if err = testAfterQueuing(t); err != nil {
- t.Logf("attempt %v failed: %v", i, err)
- }
- }
- if err != nil {
- t.Fatal(err)
- }
-}
-
-var slots = []int{5, 3, 6, 6, 6, 1, 1, 2, 7, 9, 4, 8, 0}
-
-type afterResult struct {
- slot int
- t Time
-}
-
-func await(slot int, result chan<- afterResult, ac <-chan Time) {
- result <- afterResult{slot, <-ac}
-}
-
-func testAfterQueuing(t *testing.T) error {
- Delta := 100 * Millisecond
- if testing.Short() {
- Delta = 20 * Millisecond
- }
- // make the result channel buffered because we don't want
- // to depend on channel queueing semantics that might
- // possibly change in the future.
- result := make(chan afterResult, len(slots))
-
- t0 := Now()
- for _, slot := range slots {
- go await(slot, result, After(Duration(slot)*Delta))
- }
- sort.Ints(slots)
- for _, slot := range slots {
- r := <-result
- if r.slot != slot {
- return fmt.Errorf("after slot %d, expected %d", r.slot, slot)
- }
- dt := r.t.Sub(t0)
- target := Duration(slot) * Delta
- if dt < target-Delta/2 || dt > target+Delta*10 {
- return fmt.Errorf("After(%s) arrived at %s, expected [%s,%s]", target, dt, target-Delta/2, target+Delta*10)
- }
- }
- return nil
-}
-
-func TestTimerStopStress(t *testing.T) {
- if testing.Short() {
- return
- }
- for i := 0; i < 100; i++ {
- go func(i int) {
- timer := AfterFunc(2*Second, func() {
- t.Fatalf("timer %d was not stopped", i)
- })
- Sleep(1 * Second)
- timer.Stop()
- }(i)
- }
- Sleep(3 * Second)
-}
-
-func TestSleepZeroDeadlock(t *testing.T) {
- // Sleep(0) used to hang, the sequence of events was as follows.
- // Sleep(0) sets G's status to Gwaiting, but then immediately returns leaving the status.
- // Then the goroutine calls e.g. new and falls down into the scheduler due to pending GC.
- // After the GC nobody wakes up the goroutine from Gwaiting status.
- defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
- c := make(chan bool)
- go func() {
- for i := 0; i < 100; i++ {
- runtime.GC()
- }
- c <- true
- }()
- for i := 0; i < 100; i++ {
- Sleep(0)
- tmp := make(chan bool, 1)
- tmp <- true
- <-tmp
- }
- <-c
-}
-
-func testReset(d Duration) error {
- t0 := NewTimer(2 * d)
- Sleep(d)
- if t0.Reset(3*d) != true {
- return errors.New("resetting unfired timer returned false")
- }
- Sleep(2 * d)
- select {
- case <-t0.C:
- return errors.New("timer fired early")
- default:
- }
- Sleep(2 * d)
- select {
- case <-t0.C:
- default:
- return errors.New("reset timer did not fire")
- }
-
- if t0.Reset(50*Millisecond) != false {
- return errors.New("resetting expired timer returned true")
- }
- return nil
-}
-
-func TestReset(t *testing.T) {
- // We try to run this test with increasingly larger multiples
- // until one works so slow, loaded hardware isn't as flaky,
- // but without slowing down fast machines unnecessarily.
- const unit = 25 * Millisecond
- tries := []Duration{
- 1 * unit,
- 3 * unit,
- 7 * unit,
- 15 * unit,
- }
- var err error
- for _, d := range tries {
- err = testReset(d)
- if err == nil {
- t.Logf("passed using duration %v", d)
- return
- }
- }
- t.Error(err)
-}
-
-// Test that sleeping for an interval so large it overflows does not
-// result in a short sleep duration.
-func TestOverflowSleep(t *testing.T) {
- const big = Duration(int64(1<<63 - 1))
- select {
- case <-After(big):
- t.Fatalf("big timeout fired")
- case <-After(25 * Millisecond):
- // OK
- }
- const neg = Duration(-1 << 63)
- select {
- case <-After(neg):
- // OK
- case <-After(1 * Second):
- t.Fatalf("negative timeout didn't fire")
- }
-}
-
-// Test that a panic while deleting a timer does not leave
-// the timers mutex held, deadlocking a ticker.Stop in a defer.
-func TestIssue5745(t *testing.T) {
- ticker := NewTicker(Hour)
- defer func() {
- // would deadlock here before the fix due to
- // lock taken before the segfault.
- ticker.Stop()
-
- if r := recover(); r == nil {
- t.Error("Expected panic, but none happened.")
- }
- }()
-
- // cause a panic due to a segfault
- var timer *Timer
- timer.Stop()
- t.Error("Should be unreachable.")
-}
-
-func TestOverflowRuntimeTimer(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping in short mode, see issue 6874")
- }
- if err := CheckRuntimeTimerOverflow(); err != nil {
- t.Fatalf(err.Error())
- }
-}
diff --git a/src/pkg/time/sys_plan9.go b/src/pkg/time/sys_plan9.go
deleted file mode 100644
index 848472944..000000000
--- a/src/pkg/time/sys_plan9.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2011 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.
-
-// +build plan9
-
-package time
-
-import (
- "errors"
- "syscall"
-)
-
-// for testing: whatever interrupts a sleep
-func interrupt() {
- // cannot predict pid, don't want to kill group
-}
-
-// readFile reads and returns the content of the named file.
-// It is a trivial implementation of ioutil.ReadFile, reimplemented
-// here to avoid depending on io/ioutil or os.
-func readFile(name string) ([]byte, error) {
- f, err := syscall.Open(name, syscall.O_RDONLY)
- if err != nil {
- return nil, err
- }
- defer syscall.Close(f)
- var (
- buf [4096]byte
- ret []byte
- n int
- )
- for {
- n, err = syscall.Read(f, buf[:])
- if n > 0 {
- ret = append(ret, buf[:n]...)
- }
- if n == 0 || err != nil {
- break
- }
- }
- return ret, err
-}
-
-func open(name string) (uintptr, error) {
- fd, err := syscall.Open(name, syscall.O_RDONLY)
- if err != nil {
- return 0, err
- }
- return uintptr(fd), nil
-}
-
-func closefd(fd uintptr) {
- syscall.Close(int(fd))
-}
-
-func preadn(fd uintptr, buf []byte, off int) error {
- whence := 0
- if off < 0 {
- whence = 2
- }
- if _, err := syscall.Seek(int(fd), int64(off), whence); err != nil {
- return err
- }
- for len(buf) > 0 {
- m, err := syscall.Read(int(fd), buf)
- if m <= 0 {
- if err == nil {
- return errors.New("short read")
- }
- return err
- }
- buf = buf[m:]
- }
- return nil
-}
diff --git a/src/pkg/time/sys_unix.go b/src/pkg/time/sys_unix.go
deleted file mode 100644
index 379e13d6a..000000000
--- a/src/pkg/time/sys_unix.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2011 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.
-
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
-
-package time
-
-import (
- "errors"
- "syscall"
-)
-
-// for testing: whatever interrupts a sleep
-func interrupt() {
- syscall.Kill(syscall.Getpid(), syscall.SIGCHLD)
-}
-
-// readFile reads and returns the content of the named file.
-// It is a trivial implementation of ioutil.ReadFile, reimplemented
-// here to avoid depending on io/ioutil or os.
-func readFile(name string) ([]byte, error) {
- f, err := syscall.Open(name, syscall.O_RDONLY, 0)
- if err != nil {
- return nil, err
- }
- defer syscall.Close(f)
- var (
- buf [4096]byte
- ret []byte
- n int
- )
- for {
- n, err = syscall.Read(f, buf[:])
- if n > 0 {
- ret = append(ret, buf[:n]...)
- }
- if n == 0 || err != nil {
- break
- }
- }
- return ret, err
-}
-
-func open(name string) (uintptr, error) {
- fd, err := syscall.Open(name, syscall.O_RDONLY, 0)
- if err != nil {
- return 0, err
- }
- return uintptr(fd), nil
-}
-
-func closefd(fd uintptr) {
- syscall.Close(int(fd))
-}
-
-func preadn(fd uintptr, buf []byte, off int) error {
- whence := 0
- if off < 0 {
- whence = 2
- }
- if _, err := syscall.Seek(int(fd), int64(off), whence); err != nil {
- return err
- }
- for len(buf) > 0 {
- m, err := syscall.Read(int(fd), buf)
- if m <= 0 {
- if err == nil {
- return errors.New("short read")
- }
- return err
- }
- buf = buf[m:]
- }
- return nil
-}
diff --git a/src/pkg/time/sys_windows.go b/src/pkg/time/sys_windows.go
deleted file mode 100644
index de63b4bf4..000000000
--- a/src/pkg/time/sys_windows.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2011 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 (
- "errors"
- "syscall"
-)
-
-// for testing: whatever interrupts a sleep
-func interrupt() {
-}
-
-// readFile reads and returns the content of the named file.
-// It is a trivial implementation of ioutil.ReadFile, reimplemented
-// here to avoid depending on io/ioutil or os.
-func readFile(name string) ([]byte, error) {
- f, err := syscall.Open(name, syscall.O_RDONLY, 0)
- if err != nil {
- return nil, err
- }
- defer syscall.Close(f)
- var (
- buf [4096]byte
- ret []byte
- n int
- )
- for {
- n, err = syscall.Read(f, buf[:])
- if n > 0 {
- ret = append(ret, buf[:n]...)
- }
- if n == 0 || err != nil {
- break
- }
- }
- return ret, err
-}
-
-func open(name string) (uintptr, error) {
- fd, err := syscall.Open(name, syscall.O_RDONLY, 0)
- if err != nil {
- return 0, err
- }
- return uintptr(fd), nil
-}
-
-func closefd(fd uintptr) {
- syscall.Close(syscall.Handle(fd))
-}
-
-func preadn(fd uintptr, buf []byte, off int) error {
- whence := 0
- if off < 0 {
- whence = 2
- }
- if _, err := syscall.Seek(syscall.Handle(fd), int64(off), whence); err != nil {
- return err
- }
- for len(buf) > 0 {
- m, err := syscall.Read(syscall.Handle(fd), buf)
- if m <= 0 {
- if err == nil {
- return errors.New("short read")
- }
- return err
- }
- buf = buf[m:]
- }
- return nil
-}
diff --git a/src/pkg/time/tick.go b/src/pkg/time/tick.go
deleted file mode 100644
index 19007841e..000000000
--- a/src/pkg/time/tick.go
+++ /dev/null
@@ -1,56 +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 "errors"
-
-// A Ticker holds a channel that delivers `ticks' of a clock
-// at intervals.
-type Ticker struct {
- C <-chan Time // The channel on which the ticks are delivered.
- r runtimeTimer
-}
-
-// NewTicker returns a new Ticker containing a channel that will send the
-// time with a period specified by the duration argument.
-// It adjusts the intervals or drops ticks to make up for slow receivers.
-// The duration d must be greater than zero; if not, NewTicker will panic.
-// Stop the ticker to release associated resources.
-func NewTicker(d Duration) *Ticker {
- if d <= 0 {
- panic(errors.New("non-positive interval for NewTicker"))
- }
- // Give the channel a 1-element time buffer.
- // If the client falls behind while reading, we drop ticks
- // on the floor until the client catches up.
- c := make(chan Time, 1)
- t := &Ticker{
- C: c,
- r: runtimeTimer{
- when: when(d),
- period: int64(d),
- f: sendTime,
- arg: c,
- },
- }
- startTimer(&t.r)
- return t
-}
-
-// Stop turns off a ticker. After Stop, no more ticks will be sent.
-// Stop does not close the channel, to prevent a read from the channel succeeding
-// incorrectly.
-func (t *Ticker) Stop() {
- stopTimer(&t.r)
-}
-
-// Tick is a convenience wrapper for NewTicker providing access to the ticking
-// channel only. Useful for clients that have no need to shut down the ticker.
-func Tick(d Duration) <-chan Time {
- if d <= 0 {
- return nil
- }
- return NewTicker(d).C
-}
diff --git a/src/pkg/time/tick_test.go b/src/pkg/time/tick_test.go
deleted file mode 100644
index 32f4740ad..000000000
--- a/src/pkg/time/tick_test.go
+++ /dev/null
@@ -1,78 +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_test
-
-import (
- "testing"
- . "time"
-)
-
-func TestTicker(t *testing.T) {
- const Count = 10
- Delta := 100 * Millisecond
- ticker := NewTicker(Delta)
- t0 := Now()
- for i := 0; i < Count; i++ {
- <-ticker.C
- }
- ticker.Stop()
- t1 := Now()
- dt := t1.Sub(t0)
- target := Delta * Count
- slop := target * 2 / 10
- if dt < target-slop || (!testing.Short() && dt > target+slop) {
- t.Fatalf("%d %s ticks took %s, expected [%s,%s]", Count, Delta, dt, target-slop, target+slop)
- }
- // Now test that the ticker stopped
- Sleep(2 * Delta)
- select {
- case <-ticker.C:
- t.Fatal("Ticker did not shut down")
- default:
- // ok
- }
-}
-
-// Test that a bug tearing down a ticker has been fixed. This routine should not deadlock.
-func TestTeardown(t *testing.T) {
- Delta := 100 * Millisecond
- if testing.Short() {
- Delta = 20 * Millisecond
- }
- for i := 0; i < 3; i++ {
- ticker := NewTicker(Delta)
- <-ticker.C
- ticker.Stop()
- }
-}
-
-// Test the Tick convenience wrapper.
-func TestTick(t *testing.T) {
- // Test that giving a negative duration returns nil.
- if got := Tick(-1); got != nil {
- t.Errorf("Tick(-1) = %v; want nil", got)
- }
-}
-
-// Test that NewTicker panics when given a duration less than zero.
-func TestNewTickerLtZeroDuration(t *testing.T) {
- defer func() {
- if err := recover(); err == nil {
- t.Errorf("NewTicker(-1) should have panicked")
- }
- }()
- NewTicker(-1)
-}
-
-func BenchmarkTicker(b *testing.B) {
- ticker := NewTicker(1)
- b.ResetTimer()
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- <-ticker.C
- }
- b.StopTimer()
- ticker.Stop()
-}
diff --git a/src/pkg/time/time.go b/src/pkg/time/time.go
deleted file mode 100644
index 0a2b09142..000000000
--- a/src/pkg/time/time.go
+++ /dev/null
@@ -1,1206 +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 provides functionality for measuring and displaying time.
-//
-// The calendrical calculations always assume a Gregorian calendar.
-package time
-
-import "errors"
-
-// A Time represents an instant in time with nanosecond precision.
-//
-// Programs using times should typically store and pass them as values,
-// not pointers. That is, time variables and struct fields should be of
-// type time.Time, not *time.Time. A Time value can be used by
-// multiple goroutines simultaneously.
-//
-// Time instants can be compared using the Before, After, and Equal methods.
-// The Sub method subtracts two instants, producing a Duration.
-// The Add method adds a Time and a Duration, producing a Time.
-//
-// The zero value of type Time is January 1, year 1, 00:00:00.000000000 UTC.
-// As this time is unlikely to come up in practice, the IsZero method gives
-// a simple way of detecting a time that has not been initialized explicitly.
-//
-// Each Time has associated with it a Location, consulted when computing the
-// presentation form of the time, such as in the Format, Hour, and Year methods.
-// The methods Local, UTC, and In return a Time with a specific location.
-// Changing the location in this way changes only the presentation; it does not
-// change the instant in time being denoted and therefore does not affect the
-// computations described in earlier paragraphs.
-//
-type Time struct {
- // sec gives the number of seconds elapsed since
- // January 1, year 1 00:00:00 UTC.
- sec int64
-
- // nsec specifies a non-negative nanosecond
- // offset within the second named by Seconds.
- // It must be in the range [0, 999999999].
- //
- // It is declared as uintptr instead of int32 or uint32
- // to avoid garbage collector aliasing in the case where
- // on a 64-bit system the int32 or uint32 field is written
- // over the low half of a pointer, creating another pointer.
- // TODO(rsc): When the garbage collector is completely
- // precise, change back to int32.
- nsec uintptr
-
- // loc specifies the Location that should be used to
- // determine the minute, hour, month, day, and year
- // that correspond to this Time.
- // Only the zero Time has a nil Location.
- // In that case it is interpreted to mean UTC.
- loc *Location
-}
-
-// After reports whether the time instant t is after u.
-func (t Time) After(u Time) bool {
- return t.sec > u.sec || t.sec == u.sec && t.nsec > u.nsec
-}
-
-// Before reports whether the time instant t is before u.
-func (t Time) Before(u Time) bool {
- return t.sec < u.sec || t.sec == u.sec && t.nsec < u.nsec
-}
-
-// Equal reports whether t and u represent the same time instant.
-// Two times can be equal even if they are in different locations.
-// For example, 6:00 +0200 CEST and 4:00 UTC are Equal.
-// This comparison is different from using t == u, which also compares
-// the locations.
-func (t Time) Equal(u Time) bool {
- return t.sec == u.sec && t.nsec == u.nsec
-}
-
-// A Month specifies a month of the year (January = 1, ...).
-type Month int
-
-const (
- January Month = 1 + iota
- February
- March
- April
- May
- June
- July
- August
- September
- October
- November
- December
-)
-
-var months = [...]string{
- "January",
- "February",
- "March",
- "April",
- "May",
- "June",
- "July",
- "August",
- "September",
- "October",
- "November",
- "December",
-}
-
-// String returns the English name of the month ("January", "February", ...).
-func (m Month) String() string { return months[m-1] }
-
-// A Weekday specifies a day of the week (Sunday = 0, ...).
-type Weekday int
-
-const (
- Sunday Weekday = iota
- Monday
- Tuesday
- Wednesday
- Thursday
- Friday
- Saturday
-)
-
-var days = [...]string{
- "Sunday",
- "Monday",
- "Tuesday",
- "Wednesday",
- "Thursday",
- "Friday",
- "Saturday",
-}
-
-// String returns the English name of the day ("Sunday", "Monday", ...).
-func (d Weekday) String() string { return days[d] }
-
-// Computations on time.
-//
-// The zero value for a Time is defined to be
-// January 1, year 1, 00:00:00.000000000 UTC
-// which (1) looks like a zero, or as close as you can get in a date
-// (1-1-1 00:00:00 UTC), (2) is unlikely enough to arise in practice to
-// be a suitable "not set" sentinel, unlike Jan 1 1970, and (3) has a
-// non-negative year even in time zones west of UTC, unlike 1-1-0
-// 00:00:00 UTC, which would be 12-31-(-1) 19:00:00 in New York.
-//
-// The zero Time value does not force a specific epoch for the time
-// representation. For example, to use the Unix epoch internally, we
-// could define that to distinguish a zero value from Jan 1 1970, that
-// time would be represented by sec=-1, nsec=1e9. However, it does
-// suggest a representation, namely using 1-1-1 00:00:00 UTC as the
-// epoch, and that's what we do.
-//
-// The Add and Sub computations are oblivious to the choice of epoch.
-//
-// The presentation computations - year, month, minute, and so on - all
-// rely heavily on division and modulus by positive constants. For
-// calendrical calculations we want these divisions to round down, even
-// for negative values, so that the remainder is always positive, but
-// Go's division (like most hardware division instructions) rounds to
-// zero. We can still do those computations and then adjust the result
-// for a negative numerator, but it's annoying to write the adjustment
-// over and over. Instead, we can change to a different epoch so long
-// ago that all the times we care about will be positive, and then round
-// to zero and round down coincide. These presentation routines already
-// have to add the zone offset, so adding the translation to the
-// alternate epoch is cheap. For example, having a non-negative time t
-// means that we can write
-//
-// sec = t % 60
-//
-// instead of
-//
-// sec = t % 60
-// if sec < 0 {
-// sec += 60
-// }
-//
-// everywhere.
-//
-// The calendar runs on an exact 400 year cycle: a 400-year calendar
-// printed for 1970-2469 will apply as well to 2470-2869. Even the days
-// of the week match up. It simplifies the computations to choose the
-// cycle boundaries so that the exceptional years are always delayed as
-// long as possible. That means choosing a year equal to 1 mod 400, so
-// that the first leap year is the 4th year, the first missed leap year
-// is the 100th year, and the missed missed leap year is the 400th year.
-// So we'd prefer instead to print a calendar for 2001-2400 and reuse it
-// for 2401-2800.
-//
-// Finally, it's convenient if the delta between the Unix epoch and
-// long-ago epoch is representable by an int64 constant.
-//
-// These three considerations—choose an epoch as early as possible, that
-// uses a year equal to 1 mod 400, and that is no more than 2⁶³ seconds
-// earlier than 1970—bring us to the year -292277022399. We refer to
-// this year as the absolute zero year, and to times measured as a uint64
-// seconds since this year as absolute times.
-//
-// Times measured as an int64 seconds since the year 1—the representation
-// used for Time's sec field—are called internal times.
-//
-// Times measured as an int64 seconds since the year 1970 are called Unix
-// times.
-//
-// It is tempting to just use the year 1 as the absolute epoch, defining
-// that the routines are only valid for years >= 1. However, the
-// routines would then be invalid when displaying the epoch in time zones
-// west of UTC, since it is year 0. It doesn't seem tenable to say that
-// printing the zero time correctly isn't supported in half the time
-// zones. By comparison, it's reasonable to mishandle some times in
-// the year -292277022399.
-//
-// All this is opaque to clients of the API and can be changed if a
-// better implementation presents itself.
-
-const (
- // The unsigned zero year for internal calculations.
- // Must be 1 mod 400, and times before it will not compute correctly,
- // but otherwise can be changed at will.
- absoluteZeroYear = -292277022399
-
- // The year of the zero Time.
- // Assumed by the unixToInternal computation below.
- internalYear = 1
-
- // The year of the zero Unix time.
- unixYear = 1970
-
- // Offsets to convert between internal and absolute or Unix times.
- absoluteToInternal int64 = (absoluteZeroYear - internalYear) * 365.2425 * secondsPerDay
- internalToAbsolute = -absoluteToInternal
-
- unixToInternal int64 = (1969*365 + 1969/4 - 1969/100 + 1969/400) * secondsPerDay
- internalToUnix int64 = -unixToInternal
-)
-
-// IsZero reports whether t represents the zero time instant,
-// January 1, year 1, 00:00:00 UTC.
-func (t Time) IsZero() bool {
- return t.sec == 0 && t.nsec == 0
-}
-
-// abs returns the time t as an absolute time, adjusted by the zone offset.
-// It is called when computing a presentation property like Month or Hour.
-func (t Time) abs() uint64 {
- l := t.loc
- // Avoid function calls when possible.
- if l == nil || l == &localLoc {
- l = l.get()
- }
- sec := t.sec + internalToUnix
- if l != &utcLoc {
- if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
- sec += int64(l.cacheZone.offset)
- } else {
- _, offset, _, _, _ := l.lookup(sec)
- sec += int64(offset)
- }
- }
- return uint64(sec + (unixToInternal + internalToAbsolute))
-}
-
-// locabs is a combination of the Zone and abs methods,
-// extracting both return values from a single zone lookup.
-func (t Time) locabs() (name string, offset int, abs uint64) {
- l := t.loc
- if l == nil || l == &localLoc {
- l = l.get()
- }
- // Avoid function call if we hit the local time cache.
- sec := t.sec + internalToUnix
- if l != &utcLoc {
- if l.cacheZone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
- name = l.cacheZone.name
- offset = l.cacheZone.offset
- } else {
- name, offset, _, _, _ = l.lookup(sec)
- }
- sec += int64(offset)
- } else {
- name = "UTC"
- }
- abs = uint64(sec + (unixToInternal + internalToAbsolute))
- return
-}
-
-// Date returns the year, month, and day in which t occurs.
-func (t Time) Date() (year int, month Month, day int) {
- year, month, day, _ = t.date(true)
- return
-}
-
-// Year returns the year in which t occurs.
-func (t Time) Year() int {
- year, _, _, _ := t.date(false)
- return year
-}
-
-// Month returns the month of the year specified by t.
-func (t Time) Month() Month {
- _, month, _, _ := t.date(true)
- return month
-}
-
-// Day returns the day of the month specified by t.
-func (t Time) Day() int {
- _, _, day, _ := t.date(true)
- return day
-}
-
-// Weekday returns the day of the week specified by t.
-func (t Time) Weekday() Weekday {
- return absWeekday(t.abs())
-}
-
-// absWeekday is like Weekday but operates on an absolute time.
-func absWeekday(abs uint64) Weekday {
- // January 1 of the absolute year, like January 1 of 2001, was a Monday.
- sec := (abs + uint64(Monday)*secondsPerDay) % secondsPerWeek
- return Weekday(int(sec) / secondsPerDay)
-}
-
-// ISOWeek returns the ISO 8601 year and week number in which t occurs.
-// Week ranges from 1 to 53. Jan 01 to Jan 03 of year n might belong to
-// week 52 or 53 of year n-1, and Dec 29 to Dec 31 might belong to week 1
-// of year n+1.
-func (t Time) ISOWeek() (year, week int) {
- year, month, day, yday := t.date(true)
- wday := int(t.Weekday()+6) % 7 // weekday but Monday = 0.
- const (
- Mon int = iota
- Tue
- Wed
- Thu
- Fri
- Sat
- Sun
- )
-
- // Calculate week as number of Mondays in year up to
- // and including today, plus 1 because the first week is week 0.
- // Putting the + 1 inside the numerator as a + 7 keeps the
- // numerator from being negative, which would cause it to
- // round incorrectly.
- week = (yday - wday + 7) / 7
-
- // The week number is now correct under the assumption
- // that the first Monday of the year is in week 1.
- // If Jan 1 is a Tuesday, Wednesday, or Thursday, the first Monday
- // is actually in week 2.
- jan1wday := (wday - yday + 7*53) % 7
- if Tue <= jan1wday && jan1wday <= Thu {
- week++
- }
-
- // If the week number is still 0, we're in early January but in
- // the last week of last year.
- if week == 0 {
- year--
- week = 52
- // A year has 53 weeks when Jan 1 or Dec 31 is a Thursday,
- // meaning Jan 1 of the next year is a Friday
- // or it was a leap year and Jan 1 of the next year is a Saturday.
- if jan1wday == Fri || (jan1wday == Sat && isLeap(year)) {
- week++
- }
- }
-
- // December 29 to 31 are in week 1 of next year if
- // they are after the last Thursday of the year and
- // December 31 is a Monday, Tuesday, or Wednesday.
- if month == December && day >= 29 && wday < Thu {
- if dec31wday := (wday + 31 - day) % 7; Mon <= dec31wday && dec31wday <= Wed {
- year++
- week = 1
- }
- }
-
- return
-}
-
-// Clock returns the hour, minute, and second within the day specified by t.
-func (t Time) Clock() (hour, min, sec int) {
- return absClock(t.abs())
-}
-
-// absClock is like clock but operates on an absolute time.
-func absClock(abs uint64) (hour, min, sec int) {
- sec = int(abs % secondsPerDay)
- hour = sec / secondsPerHour
- sec -= hour * secondsPerHour
- min = sec / secondsPerMinute
- sec -= min * secondsPerMinute
- return
-}
-
-// Hour returns the hour within the day specified by t, in the range [0, 23].
-func (t Time) Hour() int {
- return int(t.abs()%secondsPerDay) / secondsPerHour
-}
-
-// Minute returns the minute offset within the hour specified by t, in the range [0, 59].
-func (t Time) Minute() int {
- return int(t.abs()%secondsPerHour) / secondsPerMinute
-}
-
-// Second returns the second offset within the minute specified by t, in the range [0, 59].
-func (t Time) Second() int {
- return int(t.abs() % secondsPerMinute)
-}
-
-// Nanosecond returns the nanosecond offset within the second specified by t,
-// in the range [0, 999999999].
-func (t Time) Nanosecond() int {
- return int(t.nsec)
-}
-
-// YearDay returns the day of the year specified by t, in the range [1,365] for non-leap years,
-// and [1,366] in leap years.
-func (t Time) YearDay() int {
- _, _, _, yday := t.date(false)
- return yday + 1
-}
-
-// A Duration represents the elapsed time between two instants
-// as an int64 nanosecond count. The representation limits the
-// largest representable duration to approximately 290 years.
-type Duration int64
-
-const (
- minDuration Duration = -1 << 63
- maxDuration Duration = 1<<63 - 1
-)
-
-// Common durations. There is no definition for units of Day or larger
-// to avoid confusion across daylight savings time zone transitions.
-//
-// To count the number of units in a Duration, divide:
-// second := time.Second
-// fmt.Print(int64(second/time.Millisecond)) // prints 1000
-//
-// To convert an integer number of units to a Duration, multiply:
-// seconds := 10
-// fmt.Print(time.Duration(seconds)*time.Second) // prints 10s
-//
-const (
- Nanosecond Duration = 1
- Microsecond = 1000 * Nanosecond
- Millisecond = 1000 * Microsecond
- Second = 1000 * Millisecond
- Minute = 60 * Second
- Hour = 60 * Minute
-)
-
-// String returns a string representing the duration in the form "72h3m0.5s".
-// Leading zero units are omitted. As a special case, durations less than one
-// second format use a smaller unit (milli-, micro-, or nanoseconds) to ensure
-// that the leading digit is non-zero. The zero duration formats as 0,
-// with no unit.
-func (d Duration) String() string {
- // Largest time is 2540400h10m10.000000000s
- var buf [32]byte
- w := len(buf)
-
- u := uint64(d)
- neg := d < 0
- if neg {
- u = -u
- }
-
- if u < uint64(Second) {
- // Special case: if duration is smaller than a second,
- // use smaller units, like 1.2ms
- var (
- prec int
- unit byte
- )
- switch {
- case u == 0:
- return "0"
- case u < uint64(Microsecond):
- // print nanoseconds
- prec = 0
- unit = 'n'
- case u < uint64(Millisecond):
- // print microseconds
- prec = 3
- unit = 'u'
- default:
- // print milliseconds
- prec = 6
- unit = 'm'
- }
- w -= 2
- buf[w] = unit
- buf[w+1] = 's'
- w, u = fmtFrac(buf[:w], u, prec)
- w = fmtInt(buf[:w], u)
- } else {
- w--
- buf[w] = 's'
-
- w, u = fmtFrac(buf[:w], u, 9)
-
- // u is now integer seconds
- w = fmtInt(buf[:w], u%60)
- u /= 60
-
- // u is now integer minutes
- if u > 0 {
- w--
- buf[w] = 'm'
- w = fmtInt(buf[:w], u%60)
- u /= 60
-
- // u is now integer hours
- // Stop at hours because days can be different lengths.
- if u > 0 {
- w--
- buf[w] = 'h'
- w = fmtInt(buf[:w], u)
- }
- }
- }
-
- if neg {
- w--
- buf[w] = '-'
- }
-
- return string(buf[w:])
-}
-
-// fmtFrac formats the fraction of v/10**prec (e.g., ".12345") into the
-// tail of buf, omitting trailing zeros. it omits the decimal
-// point too when the fraction is 0. It returns the index where the
-// output bytes begin and the value v/10**prec.
-func fmtFrac(buf []byte, v uint64, prec int) (nw int, nv uint64) {
- // Omit trailing zeros up to and including decimal point.
- w := len(buf)
- print := false
- for i := 0; i < prec; i++ {
- digit := v % 10
- print = print || digit != 0
- if print {
- w--
- buf[w] = byte(digit) + '0'
- }
- v /= 10
- }
- if print {
- w--
- buf[w] = '.'
- }
- return w, v
-}
-
-// fmtInt formats v into the tail of buf.
-// It returns the index where the output begins.
-func fmtInt(buf []byte, v uint64) int {
- w := len(buf)
- if v == 0 {
- w--
- buf[w] = '0'
- } else {
- for v > 0 {
- w--
- buf[w] = byte(v%10) + '0'
- v /= 10
- }
- }
- return w
-}
-
-// Nanoseconds returns the duration as an integer nanosecond count.
-func (d Duration) Nanoseconds() int64 { return int64(d) }
-
-// These methods return float64 because the dominant
-// use case is for printing a floating point number like 1.5s, and
-// a truncation to integer would make them not useful in those cases.
-// Splitting the integer and fraction ourselves guarantees that
-// converting the returned float64 to an integer rounds the same
-// way that a pure integer conversion would have, even in cases
-// where, say, float64(d.Nanoseconds())/1e9 would have rounded
-// differently.
-
-// Seconds returns the duration as a floating point number of seconds.
-func (d Duration) Seconds() float64 {
- sec := d / Second
- nsec := d % Second
- return float64(sec) + float64(nsec)*1e-9
-}
-
-// Minutes returns the duration as a floating point number of minutes.
-func (d Duration) Minutes() float64 {
- min := d / Minute
- nsec := d % Minute
- return float64(min) + float64(nsec)*(1e-9/60)
-}
-
-// Hours returns the duration as a floating point number of hours.
-func (d Duration) Hours() float64 {
- hour := d / Hour
- nsec := d % Hour
- return float64(hour) + float64(nsec)*(1e-9/60/60)
-}
-
-// Add returns the time t+d.
-func (t Time) Add(d Duration) Time {
- t.sec += int64(d / 1e9)
- nsec := int32(t.nsec) + int32(d%1e9)
- if nsec >= 1e9 {
- t.sec++
- nsec -= 1e9
- } else if nsec < 0 {
- t.sec--
- nsec += 1e9
- }
- t.nsec = uintptr(nsec)
- return t
-}
-
-// Sub returns the duration t-u. If the result exceeds the maximum (or minimum)
-// value that can be stored in a Duration, the maximum (or minimum) duration
-// will be returned.
-// To compute t-d for a duration d, use t.Add(-d).
-func (t Time) Sub(u Time) Duration {
- d := Duration(t.sec-u.sec)*Second + Duration(int32(t.nsec)-int32(u.nsec))
- // Check for overflow or underflow.
- switch {
- case u.Add(d).Equal(t):
- return d // d is correct
- case t.Before(u):
- return minDuration // t - u is negative out of range
- default:
- return maxDuration // t - u is positive out of range
- }
-}
-
-// Since returns the time elapsed since t.
-// It is shorthand for time.Now().Sub(t).
-func Since(t Time) Duration {
- return Now().Sub(t)
-}
-
-// AddDate returns the time corresponding to adding the
-// given number of years, months, and days to t.
-// For example, AddDate(-1, 2, 3) applied to January 1, 2011
-// returns March 4, 2010.
-//
-// AddDate normalizes its result in the same way that Date does,
-// so, for example, adding one month to October 31 yields
-// December 1, the normalized form for November 31.
-func (t Time) AddDate(years int, months int, days int) Time {
- year, month, day := t.Date()
- hour, min, sec := t.Clock()
- return Date(year+years, month+Month(months), day+days, hour, min, sec, int(t.nsec), t.loc)
-}
-
-const (
- secondsPerMinute = 60
- secondsPerHour = 60 * 60
- secondsPerDay = 24 * secondsPerHour
- secondsPerWeek = 7 * secondsPerDay
- daysPer400Years = 365*400 + 97
- daysPer100Years = 365*100 + 24
- daysPer4Years = 365*4 + 1
-)
-
-// date computes the year, day of year, and when full=true,
-// the month and day in which t occurs.
-func (t Time) date(full bool) (year int, month Month, day int, yday int) {
- return absDate(t.abs(), full)
-}
-
-// absDate is like date but operates on an absolute time.
-func absDate(abs uint64, full bool) (year int, month Month, day int, yday int) {
- // Split into time and day.
- d := abs / secondsPerDay
-
- // Account for 400 year cycles.
- n := d / daysPer400Years
- y := 400 * n
- d -= daysPer400Years * n
-
- // Cut off 100-year cycles.
- // The last cycle has one extra leap year, so on the last day
- // of that year, day / daysPer100Years will be 4 instead of 3.
- // Cut it back down to 3 by subtracting n>>2.
- n = d / daysPer100Years
- n -= n >> 2
- y += 100 * n
- d -= daysPer100Years * n
-
- // Cut off 4-year cycles.
- // The last cycle has a missing leap year, which does not
- // affect the computation.
- n = d / daysPer4Years
- y += 4 * n
- d -= daysPer4Years * n
-
- // Cut off years within a 4-year cycle.
- // The last year is a leap year, so on the last day of that year,
- // day / 365 will be 4 instead of 3. Cut it back down to 3
- // by subtracting n>>2.
- n = d / 365
- n -= n >> 2
- y += n
- d -= 365 * n
-
- year = int(int64(y) + absoluteZeroYear)
- yday = int(d)
-
- if !full {
- return
- }
-
- day = yday
- if isLeap(year) {
- // Leap year
- switch {
- case day > 31+29-1:
- // After leap day; pretend it wasn't there.
- day--
- case day == 31+29-1:
- // Leap day.
- month = February
- day = 29
- return
- }
- }
-
- // Estimate month on assumption that every month has 31 days.
- // The estimate may be too low by at most one month, so adjust.
- month = Month(day / 31)
- end := int(daysBefore[month+1])
- var begin int
- if day >= end {
- month++
- begin = end
- } else {
- begin = int(daysBefore[month])
- }
-
- month++ // because January is 1
- day = day - begin + 1
- return
-}
-
-// daysBefore[m] counts the number of days in a non-leap year
-// before month m begins. There is an entry for m=12, counting
-// the number of days before January of next year (365).
-var daysBefore = [...]int32{
- 0,
- 31,
- 31 + 28,
- 31 + 28 + 31,
- 31 + 28 + 31 + 30,
- 31 + 28 + 31 + 30 + 31,
- 31 + 28 + 31 + 30 + 31 + 30,
- 31 + 28 + 31 + 30 + 31 + 30 + 31,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
- 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
-}
-
-func daysIn(m Month, year int) int {
- if m == February && isLeap(year) {
- return 29
- }
- return int(daysBefore[m] - daysBefore[m-1])
-}
-
-// Provided by package runtime.
-func now() (sec int64, nsec int32)
-
-// Now returns the current local time.
-func Now() Time {
- sec, nsec := now()
- return Time{sec + unixToInternal, uintptr(nsec), Local}
-}
-
-// UTC returns t with the location set to UTC.
-func (t Time) UTC() Time {
- t.loc = UTC
- return t
-}
-
-// Local returns t with the location set to local time.
-func (t Time) Local() Time {
- t.loc = Local
- return t
-}
-
-// In returns t with the location information set to loc.
-//
-// In panics if loc is nil.
-func (t Time) In(loc *Location) Time {
- if loc == nil {
- panic("time: missing Location in call to Time.In")
- }
- t.loc = loc
- return t
-}
-
-// Location returns the time zone information associated with t.
-func (t Time) Location() *Location {
- l := t.loc
- if l == nil {
- l = UTC
- }
- return l
-}
-
-// Zone computes the time zone in effect at time t, returning the abbreviated
-// name of the zone (such as "CET") and its offset in seconds east of UTC.
-func (t Time) Zone() (name string, offset int) {
- name, offset, _, _, _ = t.loc.lookup(t.sec + internalToUnix)
- return
-}
-
-// Unix returns t as a Unix time, the number of seconds elapsed
-// since January 1, 1970 UTC.
-func (t Time) Unix() int64 {
- return t.sec + internalToUnix
-}
-
-// UnixNano returns t as a Unix time, the number of nanoseconds elapsed
-// since January 1, 1970 UTC. The result is undefined if the Unix time
-// in nanoseconds cannot be represented by an int64. Note that this
-// means the result of calling UnixNano on the zero Time is undefined.
-func (t Time) UnixNano() int64 {
- return (t.sec+internalToUnix)*1e9 + int64(t.nsec)
-}
-
-const timeBinaryVersion byte = 1
-
-// MarshalBinary implements the encoding.BinaryMarshaler interface.
-func (t Time) MarshalBinary() ([]byte, error) {
- var offsetMin int16 // minutes east of UTC. -1 is UTC.
-
- if t.Location() == &utcLoc {
- offsetMin = -1
- } else {
- _, offset := t.Zone()
- if offset%60 != 0 {
- return nil, errors.New("Time.MarshalBinary: zone offset has fractional minute")
- }
- offset /= 60
- if offset < -32768 || offset == -1 || offset > 32767 {
- return nil, errors.New("Time.MarshalBinary: unexpected zone offset")
- }
- offsetMin = int16(offset)
- }
-
- enc := []byte{
- timeBinaryVersion, // byte 0 : version
- byte(t.sec >> 56), // bytes 1-8: seconds
- byte(t.sec >> 48),
- byte(t.sec >> 40),
- byte(t.sec >> 32),
- byte(t.sec >> 24),
- byte(t.sec >> 16),
- byte(t.sec >> 8),
- byte(t.sec),
- byte(t.nsec >> 24), // bytes 9-12: nanoseconds
- byte(t.nsec >> 16),
- byte(t.nsec >> 8),
- byte(t.nsec),
- byte(offsetMin >> 8), // bytes 13-14: zone offset in minutes
- byte(offsetMin),
- }
-
- return enc, nil
-}
-
-// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
-func (t *Time) UnmarshalBinary(data []byte) error {
- buf := data
- if len(buf) == 0 {
- return errors.New("Time.UnmarshalBinary: no data")
- }
-
- if buf[0] != timeBinaryVersion {
- return errors.New("Time.UnmarshalBinary: unsupported version")
- }
-
- if len(buf) != /*version*/ 1+ /*sec*/ 8+ /*nsec*/ 4+ /*zone offset*/ 2 {
- return errors.New("Time.UnmarshalBinary: invalid length")
- }
-
- buf = buf[1:]
- t.sec = int64(buf[7]) | int64(buf[6])<<8 | int64(buf[5])<<16 | int64(buf[4])<<24 |
- int64(buf[3])<<32 | int64(buf[2])<<40 | int64(buf[1])<<48 | int64(buf[0])<<56
-
- buf = buf[8:]
- t.nsec = uintptr(int32(buf[3]) | int32(buf[2])<<8 | int32(buf[1])<<16 | int32(buf[0])<<24)
-
- buf = buf[4:]
- offset := int(int16(buf[1])|int16(buf[0])<<8) * 60
-
- if offset == -1*60 {
- t.loc = &utcLoc
- } else if _, localoff, _, _, _ := Local.lookup(t.sec + internalToUnix); offset == localoff {
- t.loc = Local
- } else {
- t.loc = FixedZone("", offset)
- }
-
- return nil
-}
-
-// TODO(rsc): Remove GobEncoder, GobDecoder, MarshalJSON, UnmarshalJSON in Go 2.
-// The same semantics will be provided by the generic MarshalBinary, MarshalText,
-// UnmarshalBinary, UnmarshalText.
-
-// GobEncode implements the gob.GobEncoder interface.
-func (t Time) GobEncode() ([]byte, error) {
- return t.MarshalBinary()
-}
-
-// GobDecode implements the gob.GobDecoder interface.
-func (t *Time) GobDecode(data []byte) error {
- return t.UnmarshalBinary(data)
-}
-
-// MarshalJSON implements the json.Marshaler interface.
-// The time is a quoted string in RFC 3339 format, with sub-second precision added if present.
-func (t Time) MarshalJSON() ([]byte, error) {
- if y := t.Year(); y < 0 || y >= 10000 {
- // RFC 3339 is clear that years are 4 digits exactly.
- // See golang.org/issue/4556#c15 for more discussion.
- return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
- }
- return []byte(t.Format(`"` + RFC3339Nano + `"`)), nil
-}
-
-// UnmarshalJSON implements the json.Unmarshaler interface.
-// The time is expected to be a quoted string in RFC 3339 format.
-func (t *Time) UnmarshalJSON(data []byte) (err error) {
- // Fractional seconds are handled implicitly by Parse.
- *t, err = Parse(`"`+RFC3339+`"`, string(data))
- return
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-// The time is formatted in RFC 3339 format, with sub-second precision added if present.
-func (t Time) MarshalText() ([]byte, error) {
- if y := t.Year(); y < 0 || y >= 10000 {
- return nil, errors.New("Time.MarshalText: year outside of range [0,9999]")
- }
- return []byte(t.Format(RFC3339Nano)), nil
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-// The time is expected to be in RFC 3339 format.
-func (t *Time) UnmarshalText(data []byte) (err error) {
- // Fractional seconds are handled implicitly by Parse.
- *t, err = Parse(RFC3339, string(data))
- return
-}
-
-// Unix returns the local Time corresponding to the given Unix time,
-// sec seconds and nsec nanoseconds since January 1, 1970 UTC.
-// It is valid to pass nsec outside the range [0, 999999999].
-func Unix(sec int64, nsec int64) Time {
- if nsec < 0 || nsec >= 1e9 {
- n := nsec / 1e9
- sec += n
- nsec -= n * 1e9
- if nsec < 0 {
- nsec += 1e9
- sec--
- }
- }
- return Time{sec + unixToInternal, uintptr(nsec), Local}
-}
-
-func isLeap(year int) bool {
- return year%4 == 0 && (year%100 != 0 || year%400 == 0)
-}
-
-// norm returns nhi, nlo such that
-// hi * base + lo == nhi * base + nlo
-// 0 <= nlo < base
-func norm(hi, lo, base int) (nhi, nlo int) {
- if lo < 0 {
- n := (-lo-1)/base + 1
- hi -= n
- lo += n * base
- }
- if lo >= base {
- n := lo / base
- hi += n
- lo -= n * base
- }
- return hi, lo
-}
-
-// Date returns the Time corresponding to
-// yyyy-mm-dd hh:mm:ss + nsec nanoseconds
-// in the appropriate zone for that time in the given location.
-//
-// The month, day, hour, min, sec, and nsec values may be outside
-// their usual ranges and will be normalized during the conversion.
-// For example, October 32 converts to November 1.
-//
-// A daylight savings time transition skips or repeats times.
-// For example, in the United States, March 13, 2011 2:15am never occurred,
-// while November 6, 2011 1:15am occurred twice. In such cases, the
-// choice of time zone, and therefore the time, is not well-defined.
-// Date returns a time that is correct in one of the two zones involved
-// in the transition, but it does not guarantee which.
-//
-// Date panics if loc is nil.
-func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time {
- if loc == nil {
- panic("time: missing Location in call to Date")
- }
-
- // Normalize month, overflowing into year.
- m := int(month) - 1
- year, m = norm(year, m, 12)
- month = Month(m) + 1
-
- // Normalize nsec, sec, min, hour, overflowing into day.
- sec, nsec = norm(sec, nsec, 1e9)
- min, sec = norm(min, sec, 60)
- hour, min = norm(hour, min, 60)
- day, hour = norm(day, hour, 24)
-
- y := uint64(int64(year) - absoluteZeroYear)
-
- // Compute days since the absolute epoch.
-
- // Add in days from 400-year cycles.
- n := y / 400
- y -= 400 * n
- d := daysPer400Years * n
-
- // Add in 100-year cycles.
- n = y / 100
- y -= 100 * n
- d += daysPer100Years * n
-
- // Add in 4-year cycles.
- n = y / 4
- y -= 4 * n
- d += daysPer4Years * n
-
- // Add in non-leap years.
- n = y
- d += 365 * n
-
- // Add in days before this month.
- d += uint64(daysBefore[month-1])
- if isLeap(year) && month >= March {
- d++ // February 29
- }
-
- // Add in days before today.
- d += uint64(day - 1)
-
- // Add in time elapsed today.
- abs := d * secondsPerDay
- abs += uint64(hour*secondsPerHour + min*secondsPerMinute + sec)
-
- unix := int64(abs) + (absoluteToInternal + internalToUnix)
-
- // Look for zone offset for t, so we can adjust to UTC.
- // The lookup function expects UTC, so we pass t in the
- // hope that it will not be too close to a zone transition,
- // and then adjust if it is.
- _, offset, _, start, end := loc.lookup(unix)
- if offset != 0 {
- switch utc := unix - int64(offset); {
- case utc < start:
- _, offset, _, _, _ = loc.lookup(start - 1)
- case utc >= end:
- _, offset, _, _, _ = loc.lookup(end)
- }
- unix -= int64(offset)
- }
-
- return Time{unix + unixToInternal, uintptr(nsec), loc}
-}
-
-// Truncate returns the result of rounding t down to a multiple of d (since the zero time).
-// If d <= 0, Truncate returns t unchanged.
-func (t Time) Truncate(d Duration) Time {
- if d <= 0 {
- return t
- }
- _, r := div(t, d)
- return t.Add(-r)
-}
-
-// Round returns the result of rounding t to the nearest multiple of d (since the zero time).
-// The rounding behavior for halfway values is to round up.
-// If d <= 0, Round returns t unchanged.
-func (t Time) Round(d Duration) Time {
- if d <= 0 {
- return t
- }
- _, r := div(t, d)
- if r+r < d {
- return t.Add(-r)
- }
- return t.Add(d - r)
-}
-
-// div divides t by d and returns the quotient parity and remainder.
-// We don't use the quotient parity anymore (round half up instead of round to even)
-// but it's still here in case we change our minds.
-func div(t Time, d Duration) (qmod2 int, r Duration) {
- neg := false
- nsec := int32(t.nsec)
- if t.sec < 0 {
- // Operate on absolute value.
- neg = true
- t.sec = -t.sec
- nsec = -nsec
- if nsec < 0 {
- nsec += 1e9
- t.sec-- // t.sec >= 1 before the -- so safe
- }
- }
-
- switch {
- // Special case: 2d divides 1 second.
- case d < Second && Second%(d+d) == 0:
- qmod2 = int(nsec/int32(d)) & 1
- r = Duration(nsec % int32(d))
-
- // Special case: d is a multiple of 1 second.
- case d%Second == 0:
- d1 := int64(d / Second)
- qmod2 = int(t.sec/d1) & 1
- r = Duration(t.sec%d1)*Second + Duration(nsec)
-
- // General case.
- // This could be faster if more cleverness were applied,
- // but it's really only here to avoid special case restrictions in the API.
- // No one will care about these cases.
- default:
- // Compute nanoseconds as 128-bit number.
- sec := uint64(t.sec)
- tmp := (sec >> 32) * 1e9
- u1 := tmp >> 32
- u0 := tmp << 32
- tmp = uint64(sec&0xFFFFFFFF) * 1e9
- u0x, u0 := u0, u0+tmp
- if u0 < u0x {
- u1++
- }
- u0x, u0 = u0, u0+uint64(nsec)
- if u0 < u0x {
- u1++
- }
-
- // Compute remainder by subtracting r<<k for decreasing k.
- // Quotient parity is whether we subtract on last round.
- d1 := uint64(d)
- for d1>>63 != 1 {
- d1 <<= 1
- }
- d0 := uint64(0)
- for {
- qmod2 = 0
- if u1 > d1 || u1 == d1 && u0 >= d0 {
- // subtract
- qmod2 = 1
- u0x, u0 = u0, u0-d0
- if u0 > u0x {
- u1--
- }
- u1 -= d1
- }
- if d1 == 0 && d0 == uint64(d) {
- break
- }
- d0 >>= 1
- d0 |= (d1 & 1) << 63
- d1 >>= 1
- }
- r = Duration(u0)
- }
-
- if neg && r != 0 {
- // If input was negative and not an exact multiple of d, we computed q, r such that
- // q*d + r = -t
- // But the right answers are given by -(q-1), d-r:
- // q*d + r = -t
- // -q*d - r = t
- // -(q-1)*d + (d - r) = t
- qmod2 ^= 1
- r = d - r
- }
- return
-}
diff --git a/src/pkg/time/time_test.go b/src/pkg/time/time_test.go
deleted file mode 100644
index 4ae7da5a4..000000000
--- a/src/pkg/time/time_test.go
+++ /dev/null
@@ -1,1081 +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_test
-
-import (
- "bytes"
- "encoding/gob"
- "encoding/json"
- "fmt"
- "math/big"
- "math/rand"
- "runtime"
- "testing"
- "testing/quick"
- . "time"
-)
-
-// We should be in PST/PDT, but if the time zone files are missing we
-// won't be. The purpose of this test is to at least explain why some of
-// the subsequent tests fail.
-func TestZoneData(t *testing.T) {
- lt := Now()
- // PST is 8 hours west, PDT is 7 hours west. We could use the name but it's not unique.
- if name, off := lt.Zone(); off != -8*60*60 && off != -7*60*60 {
- t.Errorf("Unable to find US Pacific time zone data for testing; time zone is %q offset %d", name, off)
- t.Error("Likely problem: the time zone files have not been installed.")
- }
-}
-
-// parsedTime is the struct representing a parsed time value.
-type parsedTime struct {
- Year int
- Month Month
- Day int
- Hour, Minute, Second int // 15:04:05 is 15, 4, 5.
- Nanosecond int // Fractional second.
- Weekday Weekday
- ZoneOffset int // seconds east of UTC, e.g. -7*60*60 for -0700
- Zone string // e.g., "MST"
-}
-
-type TimeTest struct {
- seconds int64
- golden parsedTime
-}
-
-var utctests = []TimeTest{
- {0, parsedTime{1970, January, 1, 0, 0, 0, 0, Thursday, 0, "UTC"}},
- {1221681866, parsedTime{2008, September, 17, 20, 4, 26, 0, Wednesday, 0, "UTC"}},
- {-1221681866, parsedTime{1931, April, 16, 3, 55, 34, 0, Thursday, 0, "UTC"}},
- {-11644473600, parsedTime{1601, January, 1, 0, 0, 0, 0, Monday, 0, "UTC"}},
- {599529660, parsedTime{1988, December, 31, 0, 1, 0, 0, Saturday, 0, "UTC"}},
- {978220860, parsedTime{2000, December, 31, 0, 1, 0, 0, Sunday, 0, "UTC"}},
-}
-
-var nanoutctests = []TimeTest{
- {0, parsedTime{1970, January, 1, 0, 0, 0, 1e8, Thursday, 0, "UTC"}},
- {1221681866, parsedTime{2008, September, 17, 20, 4, 26, 2e8, Wednesday, 0, "UTC"}},
-}
-
-var localtests = []TimeTest{
- {0, parsedTime{1969, December, 31, 16, 0, 0, 0, Wednesday, -8 * 60 * 60, "PST"}},
- {1221681866, parsedTime{2008, September, 17, 13, 4, 26, 0, Wednesday, -7 * 60 * 60, "PDT"}},
-}
-
-var nanolocaltests = []TimeTest{
- {0, parsedTime{1969, December, 31, 16, 0, 0, 1e8, Wednesday, -8 * 60 * 60, "PST"}},
- {1221681866, parsedTime{2008, September, 17, 13, 4, 26, 3e8, Wednesday, -7 * 60 * 60, "PDT"}},
-}
-
-func same(t Time, u *parsedTime) bool {
- // Check aggregates.
- year, month, day := t.Date()
- hour, min, sec := t.Clock()
- name, offset := t.Zone()
- if year != u.Year || month != u.Month || day != u.Day ||
- hour != u.Hour || min != u.Minute || sec != u.Second ||
- name != u.Zone || offset != u.ZoneOffset {
- return false
- }
- // Check individual entries.
- 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.Nanosecond() == u.Nanosecond &&
- t.Weekday() == u.Weekday
-}
-
-func TestSecondsToUTC(t *testing.T) {
- for _, test := range utctests {
- sec := test.seconds
- golden := &test.golden
- tm := Unix(sec, 0).UTC()
- newsec := tm.Unix()
- if newsec != sec {
- t.Errorf("SecondsToUTC(%d).Seconds() = %d", sec, newsec)
- }
- if !same(tm, golden) {
- t.Errorf("SecondsToUTC(%d): // %#v", sec, tm)
- t.Errorf(" want=%+v", *golden)
- t.Errorf(" have=%v", tm.Format(RFC3339+" MST"))
- }
- }
-}
-
-func TestNanosecondsToUTC(t *testing.T) {
- for _, test := range nanoutctests {
- golden := &test.golden
- nsec := test.seconds*1e9 + int64(golden.Nanosecond)
- tm := Unix(0, nsec).UTC()
- newnsec := tm.Unix()*1e9 + int64(tm.Nanosecond())
- if newnsec != nsec {
- t.Errorf("NanosecondsToUTC(%d).Nanoseconds() = %d", nsec, newnsec)
- }
- if !same(tm, golden) {
- t.Errorf("NanosecondsToUTC(%d):", nsec)
- t.Errorf(" want=%+v", *golden)
- t.Errorf(" have=%+v", tm.Format(RFC3339+" MST"))
- }
- }
-}
-
-func TestSecondsToLocalTime(t *testing.T) {
- for _, test := range localtests {
- sec := test.seconds
- golden := &test.golden
- tm := Unix(sec, 0)
- newsec := tm.Unix()
- 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.Format(RFC3339+" MST"))
- }
- }
-}
-
-func TestNanosecondsToLocalTime(t *testing.T) {
- for _, test := range nanolocaltests {
- golden := &test.golden
- nsec := test.seconds*1e9 + int64(golden.Nanosecond)
- tm := Unix(0, nsec)
- newnsec := tm.Unix()*1e9 + int64(tm.Nanosecond())
- if newnsec != nsec {
- t.Errorf("NanosecondsToLocalTime(%d).Seconds() = %d", nsec, newnsec)
- }
- if !same(tm, golden) {
- t.Errorf("NanosecondsToLocalTime(%d):", nsec)
- t.Errorf(" want=%+v", *golden)
- t.Errorf(" have=%+v", tm.Format(RFC3339+" MST"))
- }
- }
-}
-
-func TestSecondsToUTCAndBack(t *testing.T) {
- f := func(sec int64) bool { return Unix(sec, 0).UTC().Unix() == sec }
- f32 := func(sec int32) bool { return f(int64(sec)) }
- cfg := &quick.Config{MaxCount: 10000}
-
- // Try a reasonable date first, then the huge ones.
- if err := quick.Check(f32, cfg); err != nil {
- t.Fatal(err)
- }
- if err := quick.Check(f, cfg); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestNanosecondsToUTCAndBack(t *testing.T) {
- f := func(nsec int64) bool {
- t := Unix(0, nsec).UTC()
- ns := t.Unix()*1e9 + int64(t.Nanosecond())
- return ns == nsec
- }
- f32 := func(nsec int32) bool { return f(int64(nsec)) }
- cfg := &quick.Config{MaxCount: 10000}
-
- // Try a small date first, then the large ones. (The span is only a few hundred years
- // for nanoseconds in an int64.)
- if err := quick.Check(f32, cfg); err != nil {
- t.Fatal(err)
- }
- if err := quick.Check(f, cfg); err != nil {
- t.Fatal(err)
- }
-}
-
-// The time routines provide no way to get absolute time
-// (seconds since zero), but we need it to compute the right
-// answer for bizarre roundings like "to the nearest 3 ns".
-// Compute as t - year1 = (t - 1970) + (1970 - 2001) + (2001 - 1).
-// t - 1970 is returned by Unix and Nanosecond.
-// 1970 - 2001 is -(31*365+8)*86400 = -978307200 seconds.
-// 2001 - 1 is 2000*365.2425*86400 = 63113904000 seconds.
-const unixToZero = -978307200 + 63113904000
-
-// abs returns the absolute time stored in t, as seconds and nanoseconds.
-func abs(t Time) (sec, nsec int64) {
- unix := t.Unix()
- nano := t.Nanosecond()
- return unix + unixToZero, int64(nano)
-}
-
-// absString returns abs as a decimal string.
-func absString(t Time) string {
- sec, nsec := abs(t)
- if sec < 0 {
- sec = -sec
- nsec = -nsec
- if nsec < 0 {
- nsec += 1e9
- sec--
- }
- return fmt.Sprintf("-%d%09d", sec, nsec)
- }
- return fmt.Sprintf("%d%09d", sec, nsec)
-}
-
-var truncateRoundTests = []struct {
- t Time
- d Duration
-}{
- {Date(-1, January, 1, 12, 15, 30, 5e8, UTC), 3},
- {Date(-1, January, 1, 12, 15, 31, 5e8, UTC), 3},
- {Date(2012, January, 1, 12, 15, 30, 5e8, UTC), Second},
- {Date(2012, January, 1, 12, 15, 31, 5e8, UTC), Second},
-}
-
-func TestTruncateRound(t *testing.T) {
- var (
- bsec = new(big.Int)
- bnsec = new(big.Int)
- bd = new(big.Int)
- bt = new(big.Int)
- br = new(big.Int)
- bq = new(big.Int)
- b1e9 = new(big.Int)
- )
-
- b1e9.SetInt64(1e9)
-
- testOne := func(ti, tns, di int64) bool {
- t0 := Unix(ti, int64(tns)).UTC()
- d := Duration(di)
- if d < 0 {
- d = -d
- }
- if d <= 0 {
- d = 1
- }
-
- // Compute bt = absolute nanoseconds.
- sec, nsec := abs(t0)
- bsec.SetInt64(sec)
- bnsec.SetInt64(nsec)
- bt.Mul(bsec, b1e9)
- bt.Add(bt, bnsec)
-
- // Compute quotient and remainder mod d.
- bd.SetInt64(int64(d))
- bq.DivMod(bt, bd, br)
-
- // To truncate, subtract remainder.
- // br is < d, so it fits in an int64.
- r := br.Int64()
- t1 := t0.Add(-Duration(r))
-
- // Check that time.Truncate works.
- if trunc := t0.Truncate(d); trunc != t1 {
- t.Errorf("Time.Truncate(%s, %s) = %s, want %s\n"+
- "%v trunc %v =\n%v want\n%v",
- t0.Format(RFC3339Nano), d, trunc, t1.Format(RFC3339Nano),
- absString(t0), int64(d), absString(trunc), absString(t1))
- return false
- }
-
- // To round, add d back if remainder r > d/2 or r == exactly d/2.
- // The commented out code would round half to even instead of up,
- // but that makes it time-zone dependent, which is a bit strange.
- if r > int64(d)/2 || r+r == int64(d) /*&& bq.Bit(0) == 1*/ {
- t1 = t1.Add(Duration(d))
- }
-
- // Check that time.Round works.
- if rnd := t0.Round(d); rnd != t1 {
- t.Errorf("Time.Round(%s, %s) = %s, want %s\n"+
- "%v round %v =\n%v want\n%v",
- t0.Format(RFC3339Nano), d, rnd, t1.Format(RFC3339Nano),
- absString(t0), int64(d), absString(rnd), absString(t1))
- return false
- }
- return true
- }
-
- // manual test cases
- for _, tt := range truncateRoundTests {
- testOne(tt.t.Unix(), int64(tt.t.Nanosecond()), int64(tt.d))
- }
-
- // exhaustive near 0
- for i := 0; i < 100; i++ {
- for j := 1; j < 100; j++ {
- testOne(unixToZero, int64(i), int64(j))
- testOne(unixToZero, -int64(i), int64(j))
- if t.Failed() {
- return
- }
- }
- }
-
- if t.Failed() {
- return
- }
-
- // randomly generated test cases
- cfg := &quick.Config{MaxCount: 100000}
- if testing.Short() {
- cfg.MaxCount = 1000
- }
-
- // divisors of Second
- f1 := func(ti int64, tns int32, logdi int32) bool {
- d := Duration(1)
- a, b := uint(logdi%9), (logdi>>16)%9
- d <<= a
- for i := 0; i < int(b); i++ {
- d *= 5
- }
- return testOne(ti, int64(tns), int64(d))
- }
- quick.Check(f1, cfg)
-
- // multiples of Second
- f2 := func(ti int64, tns int32, di int32) bool {
- d := Duration(di) * Second
- if d < 0 {
- d = -d
- }
- return testOne(ti, int64(tns), int64(d))
- }
- quick.Check(f2, cfg)
-
- // halfway cases
- f3 := func(tns, di int64) bool {
- di &= 0xfffffffe
- if di == 0 {
- di = 2
- }
- tns -= tns % di
- if tns < 0 {
- tns += di / 2
- } else {
- tns -= di / 2
- }
- return testOne(0, tns, di)
- }
- quick.Check(f3, cfg)
-
- // full generality
- f4 := func(ti int64, tns int32, di int64) bool {
- return testOne(ti, int64(tns), di)
- }
- quick.Check(f4, cfg)
-}
-
-type ISOWeekTest struct {
- year int // year
- month, day int // month and day
- yex int // expected year
- wex int // expected week
-}
-
-var isoWeekTests = []ISOWeekTest{
- {1981, 1, 1, 1981, 1}, {1982, 1, 1, 1981, 53}, {1983, 1, 1, 1982, 52},
- {1984, 1, 1, 1983, 52}, {1985, 1, 1, 1985, 1}, {1986, 1, 1, 1986, 1},
- {1987, 1, 1, 1987, 1}, {1988, 1, 1, 1987, 53}, {1989, 1, 1, 1988, 52},
- {1990, 1, 1, 1990, 1}, {1991, 1, 1, 1991, 1}, {1992, 1, 1, 1992, 1},
- {1993, 1, 1, 1992, 53}, {1994, 1, 1, 1993, 52}, {1995, 1, 2, 1995, 1},
- {1996, 1, 1, 1996, 1}, {1996, 1, 7, 1996, 1}, {1996, 1, 8, 1996, 2},
- {1997, 1, 1, 1997, 1}, {1998, 1, 1, 1998, 1}, {1999, 1, 1, 1998, 53},
- {2000, 1, 1, 1999, 52}, {2001, 1, 1, 2001, 1}, {2002, 1, 1, 2002, 1},
- {2003, 1, 1, 2003, 1}, {2004, 1, 1, 2004, 1}, {2005, 1, 1, 2004, 53},
- {2006, 1, 1, 2005, 52}, {2007, 1, 1, 2007, 1}, {2008, 1, 1, 2008, 1},
- {2009, 1, 1, 2009, 1}, {2010, 1, 1, 2009, 53}, {2010, 1, 1, 2009, 53},
- {2011, 1, 1, 2010, 52}, {2011, 1, 2, 2010, 52}, {2011, 1, 3, 2011, 1},
- {2011, 1, 4, 2011, 1}, {2011, 1, 5, 2011, 1}, {2011, 1, 6, 2011, 1},
- {2011, 1, 7, 2011, 1}, {2011, 1, 8, 2011, 1}, {2011, 1, 9, 2011, 1},
- {2011, 1, 10, 2011, 2}, {2011, 1, 11, 2011, 2}, {2011, 6, 12, 2011, 23},
- {2011, 6, 13, 2011, 24}, {2011, 12, 25, 2011, 51}, {2011, 12, 26, 2011, 52},
- {2011, 12, 27, 2011, 52}, {2011, 12, 28, 2011, 52}, {2011, 12, 29, 2011, 52},
- {2011, 12, 30, 2011, 52}, {2011, 12, 31, 2011, 52}, {1995, 1, 1, 1994, 52},
- {2012, 1, 1, 2011, 52}, {2012, 1, 2, 2012, 1}, {2012, 1, 8, 2012, 1},
- {2012, 1, 9, 2012, 2}, {2012, 12, 23, 2012, 51}, {2012, 12, 24, 2012, 52},
- {2012, 12, 30, 2012, 52}, {2012, 12, 31, 2013, 1}, {2013, 1, 1, 2013, 1},
- {2013, 1, 6, 2013, 1}, {2013, 1, 7, 2013, 2}, {2013, 12, 22, 2013, 51},
- {2013, 12, 23, 2013, 52}, {2013, 12, 29, 2013, 52}, {2013, 12, 30, 2014, 1},
- {2014, 1, 1, 2014, 1}, {2014, 1, 5, 2014, 1}, {2014, 1, 6, 2014, 2},
- {2015, 1, 1, 2015, 1}, {2016, 1, 1, 2015, 53}, {2017, 1, 1, 2016, 52},
- {2018, 1, 1, 2018, 1}, {2019, 1, 1, 2019, 1}, {2020, 1, 1, 2020, 1},
- {2021, 1, 1, 2020, 53}, {2022, 1, 1, 2021, 52}, {2023, 1, 1, 2022, 52},
- {2024, 1, 1, 2024, 1}, {2025, 1, 1, 2025, 1}, {2026, 1, 1, 2026, 1},
- {2027, 1, 1, 2026, 53}, {2028, 1, 1, 2027, 52}, {2029, 1, 1, 2029, 1},
- {2030, 1, 1, 2030, 1}, {2031, 1, 1, 2031, 1}, {2032, 1, 1, 2032, 1},
- {2033, 1, 1, 2032, 53}, {2034, 1, 1, 2033, 52}, {2035, 1, 1, 2035, 1},
- {2036, 1, 1, 2036, 1}, {2037, 1, 1, 2037, 1}, {2038, 1, 1, 2037, 53},
- {2039, 1, 1, 2038, 52}, {2040, 1, 1, 2039, 52},
-}
-
-func TestISOWeek(t *testing.T) {
- // Selected dates and corner cases
- for _, wt := range isoWeekTests {
- dt := Date(wt.year, Month(wt.month), wt.day, 0, 0, 0, 0, UTC)
- y, w := dt.ISOWeek()
- if w != wt.wex || y != wt.yex {
- t.Errorf("got %d/%d; expected %d/%d for %d-%02d-%02d",
- y, w, wt.yex, wt.wex, wt.year, wt.month, wt.day)
- }
- }
-
- // The only real invariant: Jan 04 is in week 1
- for year := 1950; year < 2100; year++ {
- if y, w := Date(year, January, 4, 0, 0, 0, 0, UTC).ISOWeek(); y != year || w != 1 {
- t.Errorf("got %d/%d; expected %d/1 for Jan 04", y, w, year)
- }
- }
-}
-
-type YearDayTest struct {
- year, month, day int
- yday int
-}
-
-// Test YearDay in several different scenarios
-// and corner cases
-var yearDayTests = []YearDayTest{
- // Non-leap-year tests
- {2007, 1, 1, 1},
- {2007, 1, 15, 15},
- {2007, 2, 1, 32},
- {2007, 2, 15, 46},
- {2007, 3, 1, 60},
- {2007, 3, 15, 74},
- {2007, 4, 1, 91},
- {2007, 12, 31, 365},
-
- // Leap-year tests
- {2008, 1, 1, 1},
- {2008, 1, 15, 15},
- {2008, 2, 1, 32},
- {2008, 2, 15, 46},
- {2008, 3, 1, 61},
- {2008, 3, 15, 75},
- {2008, 4, 1, 92},
- {2008, 12, 31, 366},
-
- // Looks like leap-year (but isn't) tests
- {1900, 1, 1, 1},
- {1900, 1, 15, 15},
- {1900, 2, 1, 32},
- {1900, 2, 15, 46},
- {1900, 3, 1, 60},
- {1900, 3, 15, 74},
- {1900, 4, 1, 91},
- {1900, 12, 31, 365},
-
- // Year one tests (non-leap)
- {1, 1, 1, 1},
- {1, 1, 15, 15},
- {1, 2, 1, 32},
- {1, 2, 15, 46},
- {1, 3, 1, 60},
- {1, 3, 15, 74},
- {1, 4, 1, 91},
- {1, 12, 31, 365},
-
- // Year minus one tests (non-leap)
- {-1, 1, 1, 1},
- {-1, 1, 15, 15},
- {-1, 2, 1, 32},
- {-1, 2, 15, 46},
- {-1, 3, 1, 60},
- {-1, 3, 15, 74},
- {-1, 4, 1, 91},
- {-1, 12, 31, 365},
-
- // 400 BC tests (leap-year)
- {-400, 1, 1, 1},
- {-400, 1, 15, 15},
- {-400, 2, 1, 32},
- {-400, 2, 15, 46},
- {-400, 3, 1, 61},
- {-400, 3, 15, 75},
- {-400, 4, 1, 92},
- {-400, 12, 31, 366},
-
- // Special Cases
-
- // Gregorian calendar change (no effect)
- {1582, 10, 4, 277},
- {1582, 10, 15, 288},
-}
-
-// Check to see if YearDay is location sensitive
-var yearDayLocations = []*Location{
- FixedZone("UTC-8", -8*60*60),
- FixedZone("UTC-4", -4*60*60),
- UTC,
- FixedZone("UTC+4", 4*60*60),
- FixedZone("UTC+8", 8*60*60),
-}
-
-func TestYearDay(t *testing.T) {
- for _, loc := range yearDayLocations {
- for _, ydt := range yearDayTests {
- dt := Date(ydt.year, Month(ydt.month), ydt.day, 0, 0, 0, 0, loc)
- yday := dt.YearDay()
- if yday != ydt.yday {
- t.Errorf("got %d, expected %d for %d-%02d-%02d in %v",
- yday, ydt.yday, ydt.year, ydt.month, ydt.day, loc)
- }
- }
- }
-}
-
-var durationTests = []struct {
- str string
- d Duration
-}{
- {"0", 0},
- {"1ns", 1 * Nanosecond},
- {"1.1us", 1100 * Nanosecond},
- {"2.2ms", 2200 * Microsecond},
- {"3.3s", 3300 * Millisecond},
- {"4m5s", 4*Minute + 5*Second},
- {"4m5.001s", 4*Minute + 5001*Millisecond},
- {"5h6m7.001s", 5*Hour + 6*Minute + 7001*Millisecond},
- {"8m0.000000001s", 8*Minute + 1*Nanosecond},
- {"2562047h47m16.854775807s", 1<<63 - 1},
- {"-2562047h47m16.854775808s", -1 << 63},
-}
-
-func TestDurationString(t *testing.T) {
- for _, tt := range durationTests {
- if str := tt.d.String(); str != tt.str {
- t.Errorf("Duration(%d).String() = %s, want %s", int64(tt.d), str, tt.str)
- }
- if tt.d > 0 {
- if str := (-tt.d).String(); str != "-"+tt.str {
- t.Errorf("Duration(%d).String() = %s, want %s", int64(-tt.d), str, "-"+tt.str)
- }
- }
- }
-}
-
-var dateTests = []struct {
- year, month, day, hour, min, sec, nsec int
- z *Location
- unix int64
-}{
- {2011, 11, 6, 1, 0, 0, 0, Local, 1320566400}, // 1:00:00 PDT
- {2011, 11, 6, 1, 59, 59, 0, Local, 1320569999}, // 1:59:59 PDT
- {2011, 11, 6, 2, 0, 0, 0, Local, 1320573600}, // 2:00:00 PST
-
- {2011, 3, 13, 1, 0, 0, 0, Local, 1300006800}, // 1:00:00 PST
- {2011, 3, 13, 1, 59, 59, 0, Local, 1300010399}, // 1:59:59 PST
- {2011, 3, 13, 3, 0, 0, 0, Local, 1300010400}, // 3:00:00 PDT
- {2011, 3, 13, 2, 30, 0, 0, Local, 1300008600}, // 2:30:00 PDT ≡ 1:30 PST
-
- // Many names for Fri Nov 18 7:56:35 PST 2011
- {2011, 11, 18, 7, 56, 35, 0, Local, 1321631795}, // Nov 18 7:56:35
- {2011, 11, 19, -17, 56, 35, 0, Local, 1321631795}, // Nov 19 -17:56:35
- {2011, 11, 17, 31, 56, 35, 0, Local, 1321631795}, // Nov 17 31:56:35
- {2011, 11, 18, 6, 116, 35, 0, Local, 1321631795}, // Nov 18 6:116:35
- {2011, 10, 49, 7, 56, 35, 0, Local, 1321631795}, // Oct 49 7:56:35
- {2011, 11, 18, 7, 55, 95, 0, Local, 1321631795}, // Nov 18 7:55:95
- {2011, 11, 18, 7, 56, 34, 1e9, Local, 1321631795}, // Nov 18 7:56:34 + 10⁹ns
- {2011, 12, -12, 7, 56, 35, 0, Local, 1321631795}, // Dec -21 7:56:35
- {2012, 1, -43, 7, 56, 35, 0, Local, 1321631795}, // Jan -52 7:56:35 2012
- {2012, int(January - 2), 18, 7, 56, 35, 0, Local, 1321631795}, // (Jan-2) 18 7:56:35 2012
- {2010, int(December + 11), 18, 7, 56, 35, 0, Local, 1321631795}, // (Dec+11) 18 7:56:35 2010
-}
-
-func TestDate(t *testing.T) {
- for _, tt := range dateTests {
- time := Date(tt.year, Month(tt.month), tt.day, tt.hour, tt.min, tt.sec, tt.nsec, tt.z)
- want := Unix(tt.unix, 0)
- if !time.Equal(want) {
- t.Errorf("Date(%d, %d, %d, %d, %d, %d, %d, %s) = %v, want %v",
- tt.year, tt.month, tt.day, tt.hour, tt.min, tt.sec, tt.nsec, tt.z,
- time, want)
- }
- }
-}
-
-// Several ways of getting from
-// Fri Nov 18 7:56:35 PST 2011
-// to
-// Thu Mar 19 7:56:35 PST 2016
-var addDateTests = []struct {
- years, months, days int
-}{
- {4, 4, 1},
- {3, 16, 1},
- {3, 15, 30},
- {5, -6, -18 - 30 - 12},
-}
-
-func TestAddDate(t *testing.T) {
- t0 := Date(2011, 11, 18, 7, 56, 35, 0, UTC)
- t1 := Date(2016, 3, 19, 7, 56, 35, 0, UTC)
- for _, at := range addDateTests {
- time := t0.AddDate(at.years, at.months, at.days)
- if !time.Equal(t1) {
- t.Errorf("AddDate(%d, %d, %d) = %v, want %v",
- at.years, at.months, at.days,
- time, t1)
- }
- }
-}
-
-var daysInTests = []struct {
- year, month, di int
-}{
- {2011, 1, 31}, // January, first month, 31 days
- {2011, 2, 28}, // February, non-leap year, 28 days
- {2012, 2, 29}, // February, leap year, 29 days
- {2011, 6, 30}, // June, 30 days
- {2011, 12, 31}, // December, last month, 31 days
-}
-
-func TestDaysIn(t *testing.T) {
- // The daysIn function is not exported.
- // Test the daysIn function via the `var DaysIn = daysIn`
- // statement in the internal_test.go file.
- for _, tt := range daysInTests {
- di := DaysIn(Month(tt.month), tt.year)
- if di != tt.di {
- t.Errorf("got %d; expected %d for %d-%02d",
- di, tt.di, tt.year, tt.month)
- }
- }
-}
-
-func TestAddToExactSecond(t *testing.T) {
- // Add an amount to the current time to round it up to the next exact second.
- // This test checks that the nsec field still lies within the range [0, 999999999].
- t1 := Now()
- t2 := t1.Add(Second - Duration(t1.Nanosecond()))
- sec := (t1.Second() + 1) % 60
- if t2.Second() != sec || t2.Nanosecond() != 0 {
- t.Errorf("sec = %d, nsec = %d, want sec = %d, nsec = 0", t2.Second(), t2.Nanosecond(), sec)
- }
-}
-
-func equalTimeAndZone(a, b Time) bool {
- aname, aoffset := a.Zone()
- bname, boffset := b.Zone()
- return a.Equal(b) && aoffset == boffset && aname == bname
-}
-
-var gobTests = []Time{
- Date(0, 1, 2, 3, 4, 5, 6, UTC),
- Date(7, 8, 9, 10, 11, 12, 13, FixedZone("", 0)),
- Unix(81985467080890095, 0x76543210), // Time.sec: 0x0123456789ABCDEF
- {}, // nil location
- Date(1, 2, 3, 4, 5, 6, 7, FixedZone("", 32767*60)),
- Date(1, 2, 3, 4, 5, 6, 7, FixedZone("", -32768*60)),
-}
-
-func TestTimeGob(t *testing.T) {
- var b bytes.Buffer
- enc := gob.NewEncoder(&b)
- dec := gob.NewDecoder(&b)
- for _, tt := range gobTests {
- var gobtt Time
- if err := enc.Encode(&tt); err != nil {
- t.Errorf("%v gob Encode error = %q, want nil", tt, err)
- } else if err := dec.Decode(&gobtt); err != nil {
- t.Errorf("%v gob Decode error = %q, want nil", tt, err)
- } else if !equalTimeAndZone(gobtt, tt) {
- t.Errorf("Decoded time = %v, want %v", gobtt, tt)
- }
- b.Reset()
- }
-}
-
-var invalidEncodingTests = []struct {
- bytes []byte
- want string
-}{
- {[]byte{}, "Time.UnmarshalBinary: no data"},
- {[]byte{0, 2, 3}, "Time.UnmarshalBinary: unsupported version"},
- {[]byte{1, 2, 3}, "Time.UnmarshalBinary: invalid length"},
-}
-
-func TestInvalidTimeGob(t *testing.T) {
- for _, tt := range invalidEncodingTests {
- var ignored Time
- err := ignored.GobDecode(tt.bytes)
- if err == nil || err.Error() != tt.want {
- t.Errorf("time.GobDecode(%#v) error = %v, want %v", tt.bytes, err, tt.want)
- }
- err = ignored.UnmarshalBinary(tt.bytes)
- if err == nil || err.Error() != tt.want {
- t.Errorf("time.UnmarshalBinary(%#v) error = %v, want %v", tt.bytes, err, tt.want)
- }
- }
-}
-
-var notEncodableTimes = []struct {
- time Time
- want string
-}{
- {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", 1)), "Time.MarshalBinary: zone offset has fractional minute"},
- {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", -1*60)), "Time.MarshalBinary: unexpected zone offset"},
- {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", -32769*60)), "Time.MarshalBinary: unexpected zone offset"},
- {Date(0, 1, 2, 3, 4, 5, 6, FixedZone("", 32768*60)), "Time.MarshalBinary: unexpected zone offset"},
-}
-
-func TestNotGobEncodableTime(t *testing.T) {
- for _, tt := range notEncodableTimes {
- _, err := tt.time.GobEncode()
- if err == nil || err.Error() != tt.want {
- t.Errorf("%v GobEncode error = %v, want %v", tt.time, err, tt.want)
- }
- _, err = tt.time.MarshalBinary()
- if err == nil || err.Error() != tt.want {
- t.Errorf("%v MarshalBinary error = %v, want %v", tt.time, err, tt.want)
- }
- }
-}
-
-var jsonTests = []struct {
- time Time
- json string
-}{
- {Date(9999, 4, 12, 23, 20, 50, 520*1e6, UTC), `"9999-04-12T23:20:50.52Z"`},
- {Date(1996, 12, 19, 16, 39, 57, 0, Local), `"1996-12-19T16:39:57-08:00"`},
- {Date(0, 1, 1, 0, 0, 0, 1, FixedZone("", 1*60)), `"0000-01-01T00:00:00.000000001+00:01"`},
-}
-
-func TestTimeJSON(t *testing.T) {
- for _, tt := range jsonTests {
- var jsonTime Time
-
- if jsonBytes, err := json.Marshal(tt.time); err != nil {
- t.Errorf("%v json.Marshal error = %v, want nil", tt.time, err)
- } else if string(jsonBytes) != tt.json {
- t.Errorf("%v JSON = %#q, want %#q", tt.time, string(jsonBytes), tt.json)
- } else if err = json.Unmarshal(jsonBytes, &jsonTime); err != nil {
- t.Errorf("%v json.Unmarshal error = %v, want nil", tt.time, err)
- } else if !equalTimeAndZone(jsonTime, tt.time) {
- t.Errorf("Unmarshaled time = %v, want %v", jsonTime, tt.time)
- }
- }
-}
-
-func TestInvalidTimeJSON(t *testing.T) {
- var tt Time
- err := json.Unmarshal([]byte(`{"now is the time":"buddy"}`), &tt)
- _, isParseErr := err.(*ParseError)
- if !isParseErr {
- t.Errorf("expected *time.ParseError unmarshaling JSON, got %v", err)
- }
-}
-
-var notJSONEncodableTimes = []struct {
- time Time
- want string
-}{
- {Date(10000, 1, 1, 0, 0, 0, 0, UTC), "Time.MarshalJSON: year outside of range [0,9999]"},
- {Date(-1, 1, 1, 0, 0, 0, 0, UTC), "Time.MarshalJSON: year outside of range [0,9999]"},
-}
-
-func TestNotJSONEncodableTime(t *testing.T) {
- for _, tt := range notJSONEncodableTimes {
- _, err := tt.time.MarshalJSON()
- if err == nil || err.Error() != tt.want {
- t.Errorf("%v MarshalJSON error = %v, want %v", tt.time, err, tt.want)
- }
- }
-}
-
-var parseDurationTests = []struct {
- in string
- ok bool
- want Duration
-}{
- // simple
- {"0", true, 0},
- {"5s", true, 5 * Second},
- {"30s", true, 30 * Second},
- {"1478s", true, 1478 * Second},
- // sign
- {"-5s", true, -5 * Second},
- {"+5s", true, 5 * Second},
- {"-0", true, 0},
- {"+0", true, 0},
- // decimal
- {"5.0s", true, 5 * Second},
- {"5.6s", true, 5*Second + 600*Millisecond},
- {"5.s", true, 5 * Second},
- {".5s", true, 500 * Millisecond},
- {"1.0s", true, 1 * Second},
- {"1.00s", true, 1 * Second},
- {"1.004s", true, 1*Second + 4*Millisecond},
- {"1.0040s", true, 1*Second + 4*Millisecond},
- {"100.00100s", true, 100*Second + 1*Millisecond},
- // different units
- {"10ns", true, 10 * Nanosecond},
- {"11us", true, 11 * Microsecond},
- {"12µs", true, 12 * Microsecond}, // U+00B5
- {"12μs", true, 12 * Microsecond}, // U+03BC
- {"13ms", true, 13 * Millisecond},
- {"14s", true, 14 * Second},
- {"15m", true, 15 * Minute},
- {"16h", true, 16 * Hour},
- // composite durations
- {"3h30m", true, 3*Hour + 30*Minute},
- {"10.5s4m", true, 4*Minute + 10*Second + 500*Millisecond},
- {"-2m3.4s", true, -(2*Minute + 3*Second + 400*Millisecond)},
- {"1h2m3s4ms5us6ns", true, 1*Hour + 2*Minute + 3*Second + 4*Millisecond + 5*Microsecond + 6*Nanosecond},
- {"39h9m14.425s", true, 39*Hour + 9*Minute + 14*Second + 425*Millisecond},
- // large value
- {"52763797000ns", true, 52763797000 * Nanosecond},
- // more than 9 digits after decimal point, see http://golang.org/issue/6617
- {"0.3333333333333333333h", true, 20 * Minute},
-
- // errors
- {"", false, 0},
- {"3", false, 0},
- {"-", false, 0},
- {"s", false, 0},
- {".", false, 0},
- {"-.", false, 0},
- {".s", false, 0},
- {"+.s", false, 0},
- {"3000000h", false, 0}, // overflow
-}
-
-func TestParseDuration(t *testing.T) {
- for _, tc := range parseDurationTests {
- d, err := ParseDuration(tc.in)
- if tc.ok && (err != nil || d != tc.want) {
- t.Errorf("ParseDuration(%q) = %v, %v, want %v, nil", tc.in, d, err, tc.want)
- } else if !tc.ok && err == nil {
- t.Errorf("ParseDuration(%q) = _, nil, want _, non-nil", tc.in)
- }
- }
-}
-
-func TestParseDurationRoundTrip(t *testing.T) {
- for i := 0; i < 100; i++ {
- // Resolutions finer than milliseconds will result in
- // imprecise round-trips.
- d0 := Duration(rand.Int31()) * Millisecond
- s := d0.String()
- d1, err := ParseDuration(s)
- if err != nil || d0 != d1 {
- t.Errorf("round-trip failed: %d => %q => %d, %v", d0, s, d1, err)
- }
- }
-}
-
-// golang.org/issue/4622
-func TestLocationRace(t *testing.T) {
- ResetLocalOnceForTest() // reset the Once to trigger the race
-
- c := make(chan string, 1)
- go func() {
- c <- Now().String()
- }()
- Now().String()
- <-c
- Sleep(100 * Millisecond)
-
- // Back to Los Angeles for subsequent tests:
- ForceUSPacificForTesting()
-}
-
-var (
- t Time
- u int64
-)
-
-var mallocTest = []struct {
- count int
- desc string
- fn func()
-}{
- {0, `time.Now()`, func() { t = Now() }},
- {0, `time.Now().UnixNano()`, func() { u = Now().UnixNano() }},
-}
-
-func TestCountMallocs(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping malloc count in short mode")
- }
- if runtime.GOMAXPROCS(0) > 1 {
- t.Skip("skipping; GOMAXPROCS>1")
- }
- for _, mt := range mallocTest {
- allocs := int(testing.AllocsPerRun(100, mt.fn))
- if allocs > mt.count {
- t.Errorf("%s: %d allocs, want %d", mt.desc, allocs, mt.count)
- }
- }
-}
-
-func TestLoadFixed(t *testing.T) {
- // Issue 4064: handle locations without any zone transitions.
- loc, err := LoadLocation("Etc/GMT+1")
- if err != nil {
- t.Fatal(err)
- }
-
- // The tzdata name Etc/GMT+1 uses "east is negative",
- // but Go and most other systems use "east is positive".
- // So GMT+1 corresponds to -3600 in the Go zone, not +3600.
- name, offset := Now().In(loc).Zone()
- if name != "GMT+1" || offset != -1*60*60 {
- t.Errorf("Now().In(loc).Zone() = %q, %d, want %q, %d", name, offset, "GMT+1", -1*60*60)
- }
-}
-
-const (
- minDuration Duration = -1 << 63
- maxDuration Duration = 1<<63 - 1
-)
-
-var subTests = []struct {
- t Time
- u Time
- d Duration
-}{
- {Time{}, Time{}, Duration(0)},
- {Date(2009, 11, 23, 0, 0, 0, 1, UTC), Date(2009, 11, 23, 0, 0, 0, 0, UTC), Duration(1)},
- {Date(2009, 11, 23, 0, 0, 0, 0, UTC), Date(2009, 11, 24, 0, 0, 0, 0, UTC), -24 * Hour},
- {Date(2009, 11, 24, 0, 0, 0, 0, UTC), Date(2009, 11, 23, 0, 0, 0, 0, UTC), 24 * Hour},
- {Date(-2009, 11, 24, 0, 0, 0, 0, UTC), Date(-2009, 11, 23, 0, 0, 0, 0, UTC), 24 * Hour},
- {Time{}, Date(2109, 11, 23, 0, 0, 0, 0, UTC), Duration(minDuration)},
- {Date(2109, 11, 23, 0, 0, 0, 0, UTC), Time{}, Duration(maxDuration)},
- {Time{}, Date(-2109, 11, 23, 0, 0, 0, 0, UTC), Duration(maxDuration)},
- {Date(-2109, 11, 23, 0, 0, 0, 0, UTC), Time{}, Duration(minDuration)},
- {Date(2290, 1, 1, 0, 0, 0, 0, UTC), Date(2000, 1, 1, 0, 0, 0, 0, UTC), 290*365*24*Hour + 71*24*Hour},
- {Date(2300, 1, 1, 0, 0, 0, 0, UTC), Date(2000, 1, 1, 0, 0, 0, 0, UTC), Duration(maxDuration)},
- {Date(2000, 1, 1, 0, 0, 0, 0, UTC), Date(2290, 1, 1, 0, 0, 0, 0, UTC), -290*365*24*Hour - 71*24*Hour},
- {Date(2000, 1, 1, 0, 0, 0, 0, UTC), Date(2300, 1, 1, 0, 0, 0, 0, UTC), Duration(minDuration)},
-}
-
-func TestSub(t *testing.T) {
- for i, st := range subTests {
- got := st.t.Sub(st.u)
- if got != st.d {
- t.Errorf("#%d: Sub(%v, %v): got %v; want %v", i, st.t, st.u, got, st.d)
- }
- }
-}
-
-var nsDurationTests = []struct {
- d Duration
- want int64
-}{
- {Duration(-1000), -1000},
- {Duration(-1), -1},
- {Duration(1), 1},
- {Duration(1000), 1000},
-}
-
-func TestDurationNanoseconds(t *testing.T) {
- for _, tt := range nsDurationTests {
- if got := tt.d.Nanoseconds(); got != tt.want {
- t.Errorf("d.Nanoseconds() = %d; want: %d", got, tt.want)
- }
- }
-}
-
-var minDurationTests = []struct {
- d Duration
- want float64
-}{
- {Duration(-60000000000), -1},
- {Duration(-1), -1 / 60e9},
- {Duration(1), 1 / 60e9},
- {Duration(60000000000), 1},
-}
-
-func TestDurationMinutes(t *testing.T) {
- for _, tt := range minDurationTests {
- if got := tt.d.Minutes(); got != tt.want {
- t.Errorf("d.Minutes() = %g; want: %g", got, tt.want)
- }
- }
-}
-
-var hourDurationTests = []struct {
- d Duration
- want float64
-}{
- {Duration(-3600000000000), -1},
- {Duration(-1), -1 / 3600e9},
- {Duration(1), 1 / 3600e9},
- {Duration(3600000000000), 1},
-}
-
-func TestDurationHours(t *testing.T) {
- for _, tt := range hourDurationTests {
- if got := tt.d.Hours(); got != tt.want {
- t.Errorf("d.Hours() = %g; want: %g", got, tt.want)
- }
- }
-}
-
-func BenchmarkNow(b *testing.B) {
- for i := 0; i < b.N; i++ {
- t = Now()
- }
-}
-
-func BenchmarkNowUnixNano(b *testing.B) {
- for i := 0; i < b.N; i++ {
- u = Now().UnixNano()
- }
-}
-
-func BenchmarkFormat(b *testing.B) {
- t := Unix(1265346057, 0)
- for i := 0; i < b.N; i++ {
- t.Format("Mon Jan 2 15:04:05 2006")
- }
-}
-
-func BenchmarkFormatNow(b *testing.B) {
- // Like BenchmarkFormat, but easier, because the time zone
- // lookup cache is optimized for the present.
- t := Now()
- for i := 0; i < b.N; i++ {
- t.Format("Mon Jan 2 15:04:05 2006")
- }
-}
-
-func BenchmarkParse(b *testing.B) {
- for i := 0; i < b.N; i++ {
- Parse(ANSIC, "Mon Jan 2 15:04:05 2006")
- }
-}
-
-func BenchmarkHour(b *testing.B) {
- t := Now()
- for i := 0; i < b.N; i++ {
- _ = t.Hour()
- }
-}
-
-func BenchmarkSecond(b *testing.B) {
- t := Now()
- for i := 0; i < b.N; i++ {
- _ = t.Second()
- }
-}
-
-func BenchmarkYear(b *testing.B) {
- t := Now()
- for i := 0; i < b.N; i++ {
- _ = t.Year()
- }
-}
-
-func BenchmarkDay(b *testing.B) {
- t := Now()
- for i := 0; i < b.N; i++ {
- _ = t.Day()
- }
-}
diff --git a/src/pkg/time/zoneinfo.go b/src/pkg/time/zoneinfo.go
deleted file mode 100644
index c8e53a27c..000000000
--- a/src/pkg/time/zoneinfo.go
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright 2011 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 (
- "sync"
- "syscall"
-)
-
-// A Location maps time instants to the zone in use at that time.
-// Typically, the Location represents the collection of time offsets
-// in use in a geographical area, such as CEST and CET for central Europe.
-type Location struct {
- name string
- zone []zone
- tx []zoneTrans
-
- // Most lookups will be for the current time.
- // To avoid the binary search through tx, keep a
- // static one-element cache that gives the correct
- // zone for the time when the Location was created.
- // if cacheStart <= t <= cacheEnd,
- // lookup can return cacheZone.
- // The units for cacheStart and cacheEnd are seconds
- // since January 1, 1970 UTC, to match the argument
- // to lookup.
- cacheStart int64
- cacheEnd int64
- cacheZone *zone
-}
-
-// A zone represents a single time zone such as CEST or CET.
-type zone struct {
- name string // abbreviated name, "CET"
- offset int // seconds east of UTC
- isDST bool // is this zone Daylight Savings Time?
-}
-
-// A zoneTrans represents a single time zone transition.
-type zoneTrans struct {
- when int64 // transition time, in seconds since 1970 GMT
- index uint8 // the index of the zone that goes into effect at that time
- isstd, isutc bool // ignored - no idea what these mean
-}
-
-// alpha and omega are the beginning and end of time for zone
-// transitions.
-const (
- alpha = -1 << 63 // math.MinInt64
- omega = 1<<63 - 1 // math.MaxInt64
-)
-
-// UTC represents Universal Coordinated Time (UTC).
-var UTC *Location = &utcLoc
-
-// utcLoc is separate so that get can refer to &utcLoc
-// and ensure that it never returns a nil *Location,
-// even if a badly behaved client has changed UTC.
-var utcLoc = Location{name: "UTC"}
-
-// Local represents the system's local time zone.
-var Local *Location = &localLoc
-
-// localLoc is separate so that initLocal can initialize
-// it even if a client has changed Local.
-var localLoc Location
-var localOnce sync.Once
-
-func (l *Location) get() *Location {
- if l == nil {
- return &utcLoc
- }
- if l == &localLoc {
- localOnce.Do(initLocal)
- }
- return l
-}
-
-// String returns a descriptive name for the time zone information,
-// corresponding to the argument to LoadLocation.
-func (l *Location) String() string {
- return l.get().name
-}
-
-// FixedZone returns a Location that always uses
-// the given zone name and offset (seconds east of UTC).
-func FixedZone(name string, offset int) *Location {
- l := &Location{
- name: name,
- zone: []zone{{name, offset, false}},
- tx: []zoneTrans{{alpha, 0, false, false}},
- cacheStart: alpha,
- cacheEnd: omega,
- }
- l.cacheZone = &l.zone[0]
- return l
-}
-
-// lookup returns information about the time zone in use at an
-// instant in time expressed as seconds since January 1, 1970 00:00:00 UTC.
-//
-// The returned information gives the name of the zone (such as "CET"),
-// the start and end times bracketing sec when that zone is in effect,
-// the offset in seconds east of UTC (such as -5*60*60), and whether
-// the daylight savings is being observed at that time.
-func (l *Location) lookup(sec int64) (name string, offset int, isDST bool, start, end int64) {
- l = l.get()
-
- if len(l.zone) == 0 {
- name = "UTC"
- offset = 0
- isDST = false
- start = alpha
- end = omega
- return
- }
-
- if zone := l.cacheZone; zone != nil && l.cacheStart <= sec && sec < l.cacheEnd {
- name = zone.name
- offset = zone.offset
- isDST = zone.isDST
- start = l.cacheStart
- end = l.cacheEnd
- return
- }
-
- if len(l.tx) == 0 || sec < l.tx[0].when {
- zone := &l.zone[l.lookupFirstZone()]
- name = zone.name
- offset = zone.offset
- isDST = zone.isDST
- start = alpha
- if len(l.tx) > 0 {
- end = l.tx[0].when
- } else {
- end = omega
- }
- return
- }
-
- // Binary search for entry with largest time <= sec.
- // Not using sort.Search to avoid dependencies.
- tx := l.tx
- end = omega
- lo := 0
- hi := len(tx)
- for hi-lo > 1 {
- m := lo + (hi-lo)/2
- lim := tx[m].when
- if sec < lim {
- end = lim
- hi = m
- } else {
- lo = m
- }
- }
- zone := &l.zone[tx[lo].index]
- name = zone.name
- offset = zone.offset
- isDST = zone.isDST
- start = tx[lo].when
- // end = maintained during the search
- return
-}
-
-// lookupFirstZone returns the index of the time zone to use for times
-// before the first transition time, or when there are no transition
-// times.
-//
-// The reference implementation in localtime.c from
-// http://www.iana.org/time-zones/repository/releases/tzcode2013g.tar.gz
-// implements the following algorithm for these cases:
-// 1) If the first zone is unused by the transitions, use it.
-// 2) Otherwise, if there are transition times, and the first
-// transition is to a zone in daylight time, find the first
-// non-daylight-time zone before and closest to the first transition
-// zone.
-// 3) Otherwise, use the first zone that is not daylight time, if
-// there is one.
-// 4) Otherwise, use the first zone.
-func (l *Location) lookupFirstZone() int {
- // Case 1.
- if !l.firstZoneUsed() {
- return 0
- }
-
- // Case 2.
- if len(l.tx) > 0 && l.zone[l.tx[0].index].isDST {
- for zi := int(l.tx[0].index) - 1; zi >= 0; zi-- {
- if !l.zone[zi].isDST {
- return zi
- }
- }
- }
-
- // Case 3.
- for zi := range l.zone {
- if !l.zone[zi].isDST {
- return zi
- }
- }
-
- // Case 4.
- return 0
-}
-
-// firstZoneUsed returns whether the first zone is used by some
-// transition.
-func (l *Location) firstZoneUsed() bool {
- for _, tx := range l.tx {
- if tx.index == 0 {
- return true
- }
- }
- return false
-}
-
-// lookupName returns information about the time zone with
-// the given name (such as "EST") at the given pseudo-Unix time
-// (what the given time of day would be in UTC).
-func (l *Location) lookupName(name string, unix int64) (offset int, isDST bool, ok bool) {
- l = l.get()
-
- // First try for a zone with the right name that was actually
- // in effect at the given time. (In Sydney, Australia, both standard
- // and daylight-savings time are abbreviated "EST". Using the
- // offset helps us pick the right one for the given time.
- // It's not perfect: during the backward transition we might pick
- // either one.)
- for i := range l.zone {
- zone := &l.zone[i]
- if zone.name == name {
- nam, offset, isDST, _, _ := l.lookup(unix - int64(zone.offset))
- if nam == zone.name {
- return offset, isDST, true
- }
- }
- }
-
- // Otherwise fall back to an ordinary name match.
- for i := range l.zone {
- zone := &l.zone[i]
- if zone.name == name {
- return zone.offset, zone.isDST, true
- }
- }
-
- // Otherwise, give up.
- return
-}
-
-// NOTE(rsc): Eventually we will need to accept the POSIX TZ environment
-// syntax too, but I don't feel like implementing it today.
-
-var zoneinfo, _ = syscall.Getenv("ZONEINFO")
-
-// LoadLocation returns the Location with the given name.
-//
-// If the name is "" or "UTC", LoadLocation returns UTC.
-// If the name is "Local", LoadLocation returns Local.
-//
-// Otherwise, the name is taken to be a location name corresponding to a file
-// in the IANA Time Zone database, such as "America/New_York".
-//
-// The time zone database needed by LoadLocation may not be
-// present on all systems, especially non-Unix systems.
-// LoadLocation looks in the directory or uncompressed zip file
-// named by the ZONEINFO environment variable, if any, then looks in
-// known installation locations on Unix systems,
-// and finally looks in $GOROOT/lib/time/zoneinfo.zip.
-func LoadLocation(name string) (*Location, error) {
- if name == "" || name == "UTC" {
- return UTC, nil
- }
- if name == "Local" {
- return Local, nil
- }
- if zoneinfo != "" {
- if z, err := loadZoneFile(zoneinfo, name); err == nil {
- z.name = name
- return z, nil
- }
- }
- return loadLocation(name)
-}
diff --git a/src/pkg/time/zoneinfo_abbrs_windows.go b/src/pkg/time/zoneinfo_abbrs_windows.go
deleted file mode 100644
index 80334371f..000000000
--- a/src/pkg/time/zoneinfo_abbrs_windows.go
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright 2013 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.
-
-// generated by genzabbrs.go from
-// http://unicode.org/cldr/data/common/supplemental/windowsZones.xml
-
-package time
-
-type abbr struct {
- std string
- dst string
-}
-
-var abbrs = map[string]abbr{
- "Egypt Standard Time": {"EET", "EET"}, // Africa/Cairo
- "Morocco Standard Time": {"WET", "WEST"}, // Africa/Casablanca
- "South Africa Standard Time": {"SAST", "SAST"}, // Africa/Johannesburg
- "W. Central Africa Standard Time": {"WAT", "WAT"}, // Africa/Lagos
- "E. Africa Standard Time": {"EAT", "EAT"}, // Africa/Nairobi
- "Namibia Standard Time": {"WAT", "WAST"}, // Africa/Windhoek
- "Alaskan Standard Time": {"AKST", "AKDT"}, // America/Anchorage
- "Paraguay Standard Time": {"PYT", "PYST"}, // America/Asuncion
- "Bahia Standard Time": {"BRT", "BRST"}, // America/Bahia
- "SA Pacific Standard Time": {"COT", "COT"}, // America/Bogota
- "Argentina Standard Time": {"ART", "ART"}, // America/Buenos_Aires
- "Venezuela Standard Time": {"VET", "VET"}, // America/Caracas
- "SA Eastern Standard Time": {"GFT", "GFT"}, // America/Cayenne
- "Central Standard Time": {"CST", "CDT"}, // America/Chicago
- "Mountain Standard Time (Mexico)": {"MST", "MDT"}, // America/Chihuahua
- "Central Brazilian Standard Time": {"AMT", "AMST"}, // America/Cuiaba
- "Mountain Standard Time": {"MST", "MDT"}, // America/Denver
- "Greenland Standard Time": {"WGT", "WGST"}, // America/Godthab
- "Central America Standard Time": {"CST", "CST"}, // America/Guatemala
- "Atlantic Standard Time": {"AST", "ADT"}, // America/Halifax
- "US Eastern Standard Time": {"EST", "EDT"}, // America/Indianapolis
- "SA Western Standard Time": {"BOT", "BOT"}, // America/La_Paz
- "Pacific Standard Time": {"PST", "PDT"}, // America/Los_Angeles
- "Central Standard Time (Mexico)": {"CST", "CDT"}, // America/Mexico_City
- "Montevideo Standard Time": {"UYT", "UYST"}, // America/Montevideo
- "Eastern Standard Time": {"EST", "EDT"}, // America/New_York
- "US Mountain Standard Time": {"MST", "MST"}, // America/Phoenix
- "Canada Central Standard Time": {"CST", "CST"}, // America/Regina
- "Pacific Standard Time (Mexico)": {"PST", "PDT"}, // America/Santa_Isabel
- "Pacific SA Standard Time": {"CLT", "CLST"}, // America/Santiago
- "E. South America Standard Time": {"BRT", "BRST"}, // America/Sao_Paulo
- "Newfoundland Standard Time": {"NST", "NDT"}, // America/St_Johns
- "Central Asia Standard Time": {"ALMT", "ALMT"}, // Asia/Almaty
- "Jordan Standard Time": {"EET", "EEST"}, // Asia/Amman
- "Arabic Standard Time": {"AST", "AST"}, // Asia/Baghdad
- "Azerbaijan Standard Time": {"AZT", "AZST"}, // Asia/Baku
- "SE Asia Standard Time": {"ICT", "ICT"}, // Asia/Bangkok
- "Middle East Standard Time": {"EET", "EEST"}, // Asia/Beirut
- "India Standard Time": {"IST", "IST"}, // Asia/Calcutta
- "Sri Lanka Standard Time": {"IST", "IST"}, // Asia/Colombo
- "Syria Standard Time": {"EET", "EEST"}, // Asia/Damascus
- "Bangladesh Standard Time": {"BDT", "BDT"}, // Asia/Dhaka
- "Arabian Standard Time": {"GST", "GST"}, // Asia/Dubai
- "North Asia East Standard Time": {"IRKT", "IRKT"}, // Asia/Irkutsk
- "Israel Standard Time": {"IST", "IDT"}, // Asia/Jerusalem
- "Afghanistan Standard Time": {"AFT", "AFT"}, // Asia/Kabul
- "Pakistan Standard Time": {"PKT", "PKT"}, // Asia/Karachi
- "Nepal Standard Time": {"NPT", "NPT"}, // Asia/Katmandu
- "North Asia Standard Time": {"KRAT", "KRAT"}, // Asia/Krasnoyarsk
- "Magadan Standard Time": {"MAGT", "MAGT"}, // Asia/Magadan
- "E. Europe Standard Time": {"EET", "EEST"}, // Asia/Nicosia
- "N. Central Asia Standard Time": {"NOVT", "NOVT"}, // Asia/Novosibirsk
- "Myanmar Standard Time": {"MMT", "MMT"}, // Asia/Rangoon
- "Arab Standard Time": {"AST", "AST"}, // Asia/Riyadh
- "Korea Standard Time": {"KST", "KST"}, // Asia/Seoul
- "China Standard Time": {"CST", "CST"}, // Asia/Shanghai
- "Singapore Standard Time": {"SGT", "SGT"}, // Asia/Singapore
- "Taipei Standard Time": {"CST", "CST"}, // Asia/Taipei
- "West Asia Standard Time": {"UZT", "UZT"}, // Asia/Tashkent
- "Georgian Standard Time": {"GET", "GET"}, // Asia/Tbilisi
- "Iran Standard Time": {"IRST", "IRDT"}, // Asia/Tehran
- "Tokyo Standard Time": {"JST", "JST"}, // Asia/Tokyo
- "Ulaanbaatar Standard Time": {"ULAT", "ULAT"}, // Asia/Ulaanbaatar
- "Vladivostok Standard Time": {"VLAT", "VLAT"}, // Asia/Vladivostok
- "Yakutsk Standard Time": {"YAKT", "YAKT"}, // Asia/Yakutsk
- "Ekaterinburg Standard Time": {"YEKT", "YEKT"}, // Asia/Yekaterinburg
- "Caucasus Standard Time": {"AMT", "AMT"}, // Asia/Yerevan
- "Azores Standard Time": {"AZOT", "AZOST"}, // Atlantic/Azores
- "Cape Verde Standard Time": {"CVT", "CVT"}, // Atlantic/Cape_Verde
- "Greenwich Standard Time": {"GMT", "GMT"}, // Atlantic/Reykjavik
- "Cen. Australia Standard Time": {"CST", "CST"}, // Australia/Adelaide
- "E. Australia Standard Time": {"EST", "EST"}, // Australia/Brisbane
- "AUS Central Standard Time": {"CST", "CST"}, // Australia/Darwin
- "Tasmania Standard Time": {"EST", "EST"}, // Australia/Hobart
- "W. Australia Standard Time": {"WST", "WST"}, // Australia/Perth
- "AUS Eastern Standard Time": {"EST", "EST"}, // Australia/Sydney
- "UTC": {"GMT", "GMT"}, // Etc/GMT
- "UTC-11": {"GMT+11", "GMT+11"}, // Etc/GMT+11
- "Dateline Standard Time": {"GMT+12", "GMT+12"}, // Etc/GMT+12
- "UTC-02": {"GMT+2", "GMT+2"}, // Etc/GMT+2
- "UTC+12": {"GMT-12", "GMT-12"}, // Etc/GMT-12
- "W. Europe Standard Time": {"CET", "CEST"}, // Europe/Berlin
- "GTB Standard Time": {"EET", "EEST"}, // Europe/Bucharest
- "Central Europe Standard Time": {"CET", "CEST"}, // Europe/Budapest
- "Turkey Standard Time": {"EET", "EEST"}, // Europe/Istanbul
- "Kaliningrad Standard Time": {"FET", "FET"}, // Europe/Kaliningrad
- "FLE Standard Time": {"EET", "EEST"}, // Europe/Kiev
- "GMT Standard Time": {"GMT", "BST"}, // Europe/London
- "Russian Standard Time": {"MSK", "MSK"}, // Europe/Moscow
- "Romance Standard Time": {"CET", "CEST"}, // Europe/Paris
- "Central European Standard Time": {"CET", "CEST"}, // Europe/Warsaw
- "Mauritius Standard Time": {"MUT", "MUT"}, // Indian/Mauritius
- "Samoa Standard Time": {"WST", "WST"}, // Pacific/Apia
- "New Zealand Standard Time": {"NZST", "NZDT"}, // Pacific/Auckland
- "Fiji Standard Time": {"FJT", "FJT"}, // Pacific/Fiji
- "Central Pacific Standard Time": {"SBT", "SBT"}, // Pacific/Guadalcanal
- "Hawaiian Standard Time": {"HST", "HST"}, // Pacific/Honolulu
- "West Pacific Standard Time": {"PGT", "PGT"}, // Pacific/Port_Moresby
- "Tonga Standard Time": {"TOT", "TOT"}, // Pacific/Tongatapu
-}
diff --git a/src/pkg/time/zoneinfo_plan9.go b/src/pkg/time/zoneinfo_plan9.go
deleted file mode 100644
index 4bb0cb390..000000000
--- a/src/pkg/time/zoneinfo_plan9.go
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2011 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 Plan 9 timezone(2) files.
-
-package time
-
-import (
- "errors"
- "runtime"
- "syscall"
-)
-
-func isSpace(r rune) bool {
- return r == ' ' || r == '\t' || r == '\n'
-}
-
-// Copied from strings to avoid a dependency.
-func fields(s string) []string {
- // First count the fields.
- n := 0
- inField := false
- for _, rune := range s {
- wasInField := inField
- inField = !isSpace(rune)
- if inField && !wasInField {
- n++
- }
- }
-
- // Now create them.
- a := make([]string, n)
- na := 0
- fieldStart := -1 // Set to -1 when looking for start of field.
- for i, rune := range s {
- if isSpace(rune) {
- if fieldStart >= 0 {
- a[na] = s[fieldStart:i]
- na++
- fieldStart = -1
- }
- } else if fieldStart == -1 {
- fieldStart = i
- }
- }
- if fieldStart >= 0 { // Last field might end at EOF.
- a[na] = s[fieldStart:]
- }
- return a
-}
-
-func loadZoneDataPlan9(s string) (l *Location, err error) {
- f := fields(s)
- if len(f) < 4 {
- if len(f) == 2 && f[0] == "GMT" {
- return UTC, nil
- }
- return nil, badData
- }
-
- var zones [2]zone
-
- // standard timezone offset
- o, err := atoi(f[1])
- if err != nil {
- return nil, badData
- }
- zones[0] = zone{name: f[0], offset: o, isDST: false}
-
- // alternate timezone offset
- o, err = atoi(f[3])
- if err != nil {
- return nil, badData
- }
- zones[1] = zone{name: f[2], offset: o, isDST: true}
-
- // transition time pairs
- var tx []zoneTrans
- f = f[4:]
- for i := 0; i < len(f); i++ {
- zi := 0
- if i%2 == 0 {
- zi = 1
- }
- t, err := atoi(f[i])
- if err != nil {
- return nil, badData
- }
- t -= zones[0].offset
- tx = append(tx, zoneTrans{when: int64(t), index: uint8(zi)})
- }
-
- // Committed to succeed.
- l = &Location{zone: zones[:], tx: tx}
-
- // Fill in the cache with information about right now,
- // since that will be the most common lookup.
- sec, _ := now()
- for i := range tx {
- if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
- l.cacheStart = tx[i].when
- l.cacheEnd = omega
- if i+1 < len(tx) {
- l.cacheEnd = tx[i+1].when
- }
- l.cacheZone = &l.zone[tx[i].index]
- }
- }
-
- return l, nil
-}
-
-func loadZoneFilePlan9(name string) (*Location, error) {
- b, err := readFile(name)
- if err != nil {
- return nil, err
- }
- return loadZoneDataPlan9(string(b))
-}
-
-func initTestingZone() {
- z, err := loadLocation("America/Los_Angeles")
- if err != nil {
- panic("cannot load America/Los_Angeles for testing: " + err.Error())
- }
- z.name = "Local"
- localLoc = *z
-}
-
-func initLocal() {
- t, ok := syscall.Getenv("timezone")
- if ok {
- if z, err := loadZoneDataPlan9(t); err == nil {
- localLoc = *z
- return
- }
- } else {
- if z, err := loadZoneFilePlan9("/adm/timezone/local"); err == nil {
- localLoc = *z
- localLoc.name = "Local"
- return
- }
- }
-
- // Fall back to UTC.
- localLoc.name = "UTC"
-}
-
-func loadLocation(name string) (*Location, error) {
- if z, err := loadZoneFile(runtime.GOROOT()+"/lib/time/zoneinfo.zip", name); err == nil {
- z.name = name
- return z, nil
- }
- return nil, errors.New("unknown time zone " + name)
-}
-
-func forceZipFileForTesting(zipOnly bool) {
- // We only use the zip file anyway.
-}
diff --git a/src/pkg/time/zoneinfo_read.go b/src/pkg/time/zoneinfo_read.go
deleted file mode 100644
index de9ebb41c..000000000
--- a/src/pkg/time/zoneinfo_read.go
+++ /dev/null
@@ -1,343 +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 "errors"
-
-// 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:]
- 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)
-}
-
-var badData = errors.New("malformed time zone information")
-
-func loadZoneData(bytes []byte) (l *Location, err error) {
- d := data{bytes, false}
-
- // 4-byte magic "TZif"
- if magic := d.read(4); string(magic) != "TZif" {
- return nil, badData
- }
-
- // 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' && p[0] != '3' {
- return nil, badData
- }
-
- // 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, badData
- }
- 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
- d.read(n[NLeap] * 8)
-
- // 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, badData
- }
-
- // If version == 2 or 3, 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]
- zone := make([]zone, n[NZone])
- for i := range zone {
- var ok bool
- var n uint32
- if n, ok = zonedata.big4(); !ok {
- return nil, badData
- }
- zone[i].offset = int(int32(n))
- var b byte
- if b, ok = zonedata.byte(); !ok {
- return nil, badData
- }
- zone[i].isDST = b != 0
- if b, ok = zonedata.byte(); !ok || int(b) >= len(abbrev) {
- return nil, badData
- }
- zone[i].name = byteString(abbrev[b:])
- }
-
- // Now the transition time info.
- tx := make([]zoneTrans, n[NTime])
- for i := range tx {
- var ok bool
- var n uint32
- if n, ok = txtimes.big4(); !ok {
- return nil, badData
- }
- tx[i].when = int64(int32(n))
- if int(txzones[i]) >= len(zone) {
- return nil, badData
- }
- tx[i].index = txzones[i]
- if i < len(isstd) {
- tx[i].isstd = isstd[i] != 0
- }
- if i < len(isutc) {
- tx[i].isutc = isutc[i] != 0
- }
- }
-
- if len(tx) == 0 {
- // Build fake transition to cover all time.
- // This happens in fixed locations like "Etc/GMT0".
- tx = append(tx, zoneTrans{when: alpha, index: 0})
- }
-
- // Committed to succeed.
- l = &Location{zone: zone, tx: tx}
-
- // Fill in the cache with information about right now,
- // since that will be the most common lookup.
- sec, _ := now()
- for i := range tx {
- if tx[i].when <= sec && (i+1 == len(tx) || sec < tx[i+1].when) {
- l.cacheStart = tx[i].when
- l.cacheEnd = omega
- if i+1 < len(tx) {
- l.cacheEnd = tx[i+1].when
- }
- l.cacheZone = &l.zone[tx[i].index]
- }
- }
-
- return l, nil
-}
-
-func loadZoneFile(dir, name string) (l *Location, err error) {
- if len(dir) > 4 && dir[len(dir)-4:] == ".zip" {
- return loadZoneZip(dir, name)
- }
- if dir != "" {
- name = dir + "/" + name
- }
- buf, err := readFile(name)
- if err != nil {
- return
- }
- return loadZoneData(buf)
-}
-
-// There are 500+ zoneinfo files. Rather than distribute them all
-// individually, we ship them in an uncompressed zip file.
-// Used this way, the zip file format serves as a commonly readable
-// container for the individual small files. We choose zip over tar
-// because zip files have a contiguous table of contents, making
-// individual file lookups faster, and because the per-file overhead
-// in a zip file is considerably less than tar's 512 bytes.
-
-// get4 returns the little-endian 32-bit value in b.
-func get4(b []byte) int {
- if len(b) < 4 {
- return 0
- }
- return int(b[0]) | int(b[1])<<8 | int(b[2])<<16 | int(b[3])<<24
-}
-
-// get2 returns the little-endian 16-bit value in b.
-func get2(b []byte) int {
- if len(b) < 2 {
- return 0
- }
- return int(b[0]) | int(b[1])<<8
-}
-
-func loadZoneZip(zipfile, name string) (l *Location, err error) {
- fd, err := open(zipfile)
- if err != nil {
- return nil, errors.New("open " + zipfile + ": " + err.Error())
- }
- defer closefd(fd)
-
- const (
- zecheader = 0x06054b50
- zcheader = 0x02014b50
- ztailsize = 22
-
- zheadersize = 30
- zheader = 0x04034b50
- )
-
- buf := make([]byte, ztailsize)
- if err := preadn(fd, buf, -ztailsize); err != nil || get4(buf) != zecheader {
- return nil, errors.New("corrupt zip file " + zipfile)
- }
- n := get2(buf[10:])
- size := get4(buf[12:])
- off := get4(buf[16:])
-
- buf = make([]byte, size)
- if err := preadn(fd, buf, off); err != nil {
- return nil, errors.New("corrupt zip file " + zipfile)
- }
-
- for i := 0; i < n; i++ {
- // zip entry layout:
- // 0 magic[4]
- // 4 madevers[1]
- // 5 madeos[1]
- // 6 extvers[1]
- // 7 extos[1]
- // 8 flags[2]
- // 10 meth[2]
- // 12 modtime[2]
- // 14 moddate[2]
- // 16 crc[4]
- // 20 csize[4]
- // 24 uncsize[4]
- // 28 namelen[2]
- // 30 xlen[2]
- // 32 fclen[2]
- // 34 disknum[2]
- // 36 iattr[2]
- // 38 eattr[4]
- // 42 off[4]
- // 46 name[namelen]
- // 46+namelen+xlen+fclen - next header
- //
- if get4(buf) != zcheader {
- break
- }
- meth := get2(buf[10:])
- size := get4(buf[24:])
- namelen := get2(buf[28:])
- xlen := get2(buf[30:])
- fclen := get2(buf[32:])
- off := get4(buf[42:])
- zname := buf[46 : 46+namelen]
- buf = buf[46+namelen+xlen+fclen:]
- if string(zname) != name {
- continue
- }
- if meth != 0 {
- return nil, errors.New("unsupported compression for " + name + " in " + zipfile)
- }
-
- // zip per-file header layout:
- // 0 magic[4]
- // 4 extvers[1]
- // 5 extos[1]
- // 6 flags[2]
- // 8 meth[2]
- // 10 modtime[2]
- // 12 moddate[2]
- // 14 crc[4]
- // 18 csize[4]
- // 22 uncsize[4]
- // 26 namelen[2]
- // 28 xlen[2]
- // 30 name[namelen]
- // 30+namelen+xlen - file data
- //
- buf = make([]byte, zheadersize+namelen)
- if err := preadn(fd, buf, off); err != nil ||
- get4(buf) != zheader ||
- get2(buf[8:]) != meth ||
- get2(buf[26:]) != namelen ||
- string(buf[30:30+namelen]) != name {
- return nil, errors.New("corrupt zip file " + zipfile)
- }
- xlen = get2(buf[28:])
-
- buf = make([]byte, size)
- if err := preadn(fd, buf, off+30+namelen+xlen); err != nil {
- return nil, errors.New("corrupt zip file " + zipfile)
- }
-
- return loadZoneData(buf)
- }
-
- return nil, errors.New("cannot find " + name + " in zip file " + zipfile)
-}
diff --git a/src/pkg/time/zoneinfo_test.go b/src/pkg/time/zoneinfo_test.go
deleted file mode 100644
index 4ca7fad93..000000000
--- a/src/pkg/time/zoneinfo_test.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2014 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_test
-
-import (
- "testing"
- "time"
-)
-
-func TestVersion3(t *testing.T) {
- time.ForceZipFileForTesting(true)
- defer time.ForceZipFileForTesting(false)
- _, err := time.LoadLocation("Asia/Jerusalem")
- if err != nil {
- t.Fatal(err)
- }
-}
-
-// Test that we get the correct results for times before the first
-// transition time. To do this we explicitly check early dates in a
-// couple of specific timezones.
-func TestFirstZone(t *testing.T) {
- time.ForceZipFileForTesting(true)
- defer time.ForceZipFileForTesting(false)
-
- const format = "Mon, 02 Jan 2006 15:04:05 -0700 (MST)"
- var tests = []struct {
- zone string
- unix int64
- want1 string
- want2 string
- }{
- {
- "PST8PDT",
- -1633269601,
- "Sun, 31 Mar 1918 01:59:59 -0800 (PST)",
- "Sun, 31 Mar 1918 03:00:00 -0700 (PDT)",
- },
- {
- "Pacific/Fakaofo",
- 1325242799,
- "Thu, 29 Dec 2011 23:59:59 -1100 (TKT)",
- "Sat, 31 Dec 2011 00:00:00 +1300 (TKT)",
- },
- }
-
- for _, test := range tests {
- z, err := time.LoadLocation(test.zone)
- if err != nil {
- t.Fatal(err)
- }
- s := time.Unix(test.unix, 0).In(z).Format(format)
- if s != test.want1 {
- t.Errorf("for %s %d got %q want %q", test.zone, test.unix, s, test.want1)
- }
- s = time.Unix(test.unix+1, 0).In(z).Format(format)
- if s != test.want2 {
- t.Errorf("for %s %d got %q want %q", test.zone, test.unix, s, test.want2)
- }
- }
-}
diff --git a/src/pkg/time/zoneinfo_unix.go b/src/pkg/time/zoneinfo_unix.go
deleted file mode 100644
index ab7e4612e..000000000
--- a/src/pkg/time/zoneinfo_unix.go
+++ /dev/null
@@ -1,84 +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.
-
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
-
-// 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 (
- "errors"
- "runtime"
- "syscall"
-)
-
-func initTestingZone() {
- z, err := loadZoneFile(runtime.GOROOT()+"/lib/time/zoneinfo.zip", "America/Los_Angeles")
- if err != nil {
- panic("cannot load America/Los_Angeles for testing: " + err.Error())
- }
- z.name = "Local"
- localLoc = *z
-}
-
-// Many systems use /usr/share/zoneinfo, Solaris 2 has
-// /usr/share/lib/zoneinfo, IRIX 6 has /usr/lib/locale/TZ.
-var zoneDirs = []string{
- "/usr/share/zoneinfo/",
- "/usr/share/lib/zoneinfo/",
- "/usr/lib/locale/TZ/",
- runtime.GOROOT() + "/lib/time/zoneinfo.zip",
-}
-
-var origZoneDirs = zoneDirs
-
-func forceZipFileForTesting(zipOnly bool) {
- zoneDirs = make([]string, len(origZoneDirs))
- copy(zoneDirs, origZoneDirs)
- if zipOnly {
- for i := 0; i < len(zoneDirs)-1; i++ {
- zoneDirs[i] = "/XXXNOEXIST"
- }
- }
-}
-
-func initLocal() {
- // 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, ok := syscall.Getenv("TZ")
- switch {
- case !ok:
- z, err := loadZoneFile("", "/etc/localtime")
- if err == nil {
- localLoc = *z
- localLoc.name = "Local"
- return
- }
- case tz != "" && tz != "UTC":
- if z, err := loadLocation(tz); err == nil {
- localLoc = *z
- return
- }
- }
-
- // Fall back to UTC.
- localLoc.name = "UTC"
-}
-
-func loadLocation(name string) (*Location, error) {
- for _, zoneDir := range zoneDirs {
- if z, err := loadZoneFile(zoneDir, name); err == nil {
- z.name = name
- return z, nil
- }
- }
- return nil, errors.New("unknown time zone " + name)
-}
diff --git a/src/pkg/time/zoneinfo_windows.go b/src/pkg/time/zoneinfo_windows.go
deleted file mode 100644
index 6046743e6..000000000
--- a/src/pkg/time/zoneinfo_windows.go
+++ /dev/null
@@ -1,270 +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 (
- "errors"
- "runtime"
- "syscall"
- "unsafe"
-)
-
-// TODO(rsc): Fall back to copy of zoneinfo files.
-
-// BUG(brainman,rsc): On Windows, the operating system does not provide complete
-// time zone information.
-// The implementation assumes that this year's rules for daylight savings
-// time apply to all previous and future years as well.
-
-// getKeyValue retrieves the string value kname associated with the open registry key kh.
-func getKeyValue(kh syscall.Handle, kname string) (string, error) {
- var buf [50]uint16 // buf needs to be large enough to fit zone descriptions
- var typ uint32
- n := uint32(len(buf) * 2) // RegQueryValueEx's signature expects array of bytes, not uint16
- p, _ := syscall.UTF16PtrFromString(kname)
- if err := syscall.RegQueryValueEx(kh, p, nil, &typ, (*byte)(unsafe.Pointer(&buf[0])), &n); err != nil {
- return "", err
- }
- if typ != syscall.REG_SZ { // null terminated strings only
- return "", errors.New("Key is not string")
- }
- return syscall.UTF16ToString(buf[:]), nil
-}
-
-// matchZoneKey checks if stdname and dstname match the corresponding "Std"
-// and "Dlt" key values in the kname key stored under the open registry key zones.
-func matchZoneKey(zones syscall.Handle, kname string, stdname, dstname string) (matched bool, err2 error) {
- var h syscall.Handle
- p, _ := syscall.UTF16PtrFromString(kname)
- if err := syscall.RegOpenKeyEx(zones, p, 0, syscall.KEY_READ, &h); err != nil {
- return false, err
- }
- defer syscall.RegCloseKey(h)
-
- s, err := getKeyValue(h, "Std")
- if err != nil {
- return false, err
- }
- if s != stdname {
- return false, nil
- }
- s, err = getKeyValue(h, "Dlt")
- if err != nil {
- return false, err
- }
- if s != dstname && dstname != stdname {
- return false, nil
- }
- return true, nil
-}
-
-// toEnglishName searches the registry for an English name of a time zone
-// whose zone names are stdname and dstname and returns the English name.
-func toEnglishName(stdname, dstname string) (string, error) {
- var zones syscall.Handle
- p, _ := syscall.UTF16PtrFromString(`SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones`)
- if err := syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE, p, 0, syscall.KEY_READ, &zones); err != nil {
- return "", err
- }
- defer syscall.RegCloseKey(zones)
-
- var count uint32
- if err := syscall.RegQueryInfoKey(zones, nil, nil, nil, &count, nil, nil, nil, nil, nil, nil, nil); err != nil {
- return "", err
- }
-
- var buf [50]uint16 // buf needs to be large enough to fit zone descriptions
- for i := uint32(0); i < count; i++ {
- n := uint32(len(buf))
- if syscall.RegEnumKeyEx(zones, i, &buf[0], &n, nil, nil, nil, nil) != nil {
- continue
- }
- kname := syscall.UTF16ToString(buf[:])
- matched, err := matchZoneKey(zones, kname, stdname, dstname)
- if err == nil && matched {
- return kname, nil
- }
- }
- return "", errors.New(`English name for time zone "` + stdname + `" not found in registry`)
-}
-
-// extractCAPS extracts capital letters from description desc.
-func extractCAPS(desc string) string {
- var short []rune
- for _, c := range desc {
- if 'A' <= c && c <= 'Z' {
- short = append(short, rune(c))
- }
- }
- return string(short)
-}
-
-// abbrev returns the abbreviations to use for the given zone z.
-func abbrev(z *syscall.Timezoneinformation) (std, dst string) {
- stdName := syscall.UTF16ToString(z.StandardName[:])
- a, ok := abbrs[stdName]
- if !ok {
- dstName := syscall.UTF16ToString(z.DaylightName[:])
- // Perhaps stdName is not English. Try to convert it.
- englishName, err := toEnglishName(stdName, dstName)
- if err == nil {
- a, ok = abbrs[englishName]
- if ok {
- return a.std, a.dst
- }
- }
- // fallback to using capital letters
- return extractCAPS(stdName), extractCAPS(dstName)
- }
- return a.std, a.dst
-}
-
-// pseudoUnix returns the pseudo-Unix time (seconds since Jan 1 1970 *LOCAL TIME*)
-// denoted by the system date+time d in the given year.
-// It is up to the caller to convert this local time into a UTC-based time.
-func pseudoUnix(year int, d *syscall.Systemtime) int64 {
- // Windows specifies daylight savings information in "day in month" format:
- // d.Month is month number (1-12)
- // d.DayOfWeek is appropriate weekday (Sunday=0 to Saturday=6)
- // d.Day is week within the month (1 to 5, where 5 is last week of the month)
- // d.Hour, d.Minute and d.Second are absolute time
- day := 1
- t := Date(year, Month(d.Month), day, int(d.Hour), int(d.Minute), int(d.Second), 0, UTC)
- i := int(d.DayOfWeek) - int(t.Weekday())
- if i < 0 {
- i += 7
- }
- day += i
- if week := int(d.Day) - 1; week < 4 {
- day += week * 7
- } else {
- // "Last" instance of the day.
- day += 4 * 7
- if day > daysIn(Month(d.Month), year) {
- day -= 7
- }
- }
- return t.sec + int64(day-1)*secondsPerDay + internalToUnix
-}
-
-func initLocalFromTZI(i *syscall.Timezoneinformation) {
- l := &localLoc
-
- nzone := 1
- if i.StandardDate.Month > 0 {
- nzone++
- }
- l.zone = make([]zone, nzone)
-
- stdname, dstname := abbrev(i)
-
- std := &l.zone[0]
- std.name = stdname
- if nzone == 1 {
- // No daylight savings.
- std.offset = -int(i.Bias) * 60
- l.cacheStart = alpha
- l.cacheEnd = omega
- l.cacheZone = std
- l.tx = make([]zoneTrans, 1)
- l.tx[0].when = l.cacheStart
- l.tx[0].index = 0
- return
- }
-
- // StandardBias must be ignored if StandardDate is not set,
- // so this computation is delayed until after the nzone==1
- // return above.
- std.offset = -int(i.Bias+i.StandardBias) * 60
-
- dst := &l.zone[1]
- dst.name = dstname
- dst.offset = -int(i.Bias+i.DaylightBias) * 60
- dst.isDST = true
-
- // Arrange so that d0 is first transition date, d1 second,
- // i0 is index of zone after first transition, i1 second.
- d0 := &i.StandardDate
- d1 := &i.DaylightDate
- i0 := 0
- i1 := 1
- if d0.Month > d1.Month {
- d0, d1 = d1, d0
- i0, i1 = i1, i0
- }
-
- // 2 tx per year, 100 years on each side of this year
- l.tx = make([]zoneTrans, 400)
-
- t := Now().UTC()
- year := t.Year()
- txi := 0
- for y := year - 100; y < year+100; y++ {
- tx := &l.tx[txi]
- tx.when = pseudoUnix(y, d0) - int64(l.zone[i1].offset)
- tx.index = uint8(i0)
- txi++
-
- tx = &l.tx[txi]
- tx.when = pseudoUnix(y, d1) - int64(l.zone[i0].offset)
- tx.index = uint8(i1)
- txi++
- }
-}
-
-var usPacific = syscall.Timezoneinformation{
- Bias: 8 * 60,
- StandardName: [32]uint16{
- 'P', 'a', 'c', 'i', 'f', 'i', 'c', ' ', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e',
- },
- StandardDate: syscall.Systemtime{Month: 11, Day: 1, Hour: 2},
- DaylightName: [32]uint16{
- 'P', 'a', 'c', 'i', 'f', 'i', 'c', ' ', 'D', 'a', 'y', 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e',
- },
- DaylightDate: syscall.Systemtime{Month: 3, Day: 2, Hour: 2},
- DaylightBias: -60,
-}
-
-var aus = syscall.Timezoneinformation{
- Bias: -10 * 60,
- StandardName: [32]uint16{
- 'A', 'U', 'S', ' ', 'E', 'a', 's', 't', 'e', 'r', 'n', ' ', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e',
- },
- StandardDate: syscall.Systemtime{Month: 4, Day: 1, Hour: 3},
- DaylightName: [32]uint16{
- 'A', 'U', 'S', ' ', 'E', 'a', 's', 't', 'e', 'r', 'n', ' ', 'D', 'a', 'y', 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e',
- },
- DaylightDate: syscall.Systemtime{Month: 10, Day: 1, Hour: 2},
- DaylightBias: -60,
-}
-
-func initTestingZone() {
- initLocalFromTZI(&usPacific)
-}
-
-func initAusTestingZone() {
- initLocalFromTZI(&aus)
-}
-
-func initLocal() {
- var i syscall.Timezoneinformation
- if _, err := syscall.GetTimeZoneInformation(&i); err != nil {
- localLoc.name = "UTC"
- return
- }
- initLocalFromTZI(&i)
-}
-
-func loadLocation(name string) (*Location, error) {
- if z, err := loadZoneFile(runtime.GOROOT()+`\lib\time\zoneinfo.zip`, name); err == nil {
- z.name = name
- return z, nil
- }
- return nil, errors.New("unknown time zone " + name)
-}
-
-func forceZipFileForTesting(zipOnly bool) {
- // We only use the zip file anyway.
-}
diff --git a/src/pkg/time/zoneinfo_windows_test.go b/src/pkg/time/zoneinfo_windows_test.go
deleted file mode 100644
index 9db81b7cf..000000000
--- a/src/pkg/time/zoneinfo_windows_test.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 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_test
-
-import (
- "testing"
- . "time"
-)
-
-func testZoneAbbr(t *testing.T) {
- t1 := Now()
- // discard nsec
- t1 = Date(t1.Year(), t1.Month(), t1.Day(), t1.Hour(), t1.Minute(), t1.Second(), 0, t1.Location())
- t2, err := Parse(RFC1123, t1.Format(RFC1123))
- if err != nil {
- t.Fatalf("Parse failed: %v", err)
- }
- if t1 != t2 {
- t.Fatalf("t1 (%v) is not equal to t2 (%v)", t1, t2)
- }
-}
-
-func TestLocalZoneAbbr(t *testing.T) {
- ResetLocalOnceForTest() // reset the Once to trigger the race
- defer ForceUSPacificForTesting()
- testZoneAbbr(t)
-}
-
-func TestAusZoneAbbr(t *testing.T) {
- ForceAusForTesting()
- defer ForceUSPacificForTesting()
- testZoneAbbr(t)
-}