aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libgo/go/time
diff options
context:
space:
mode:
authorBen Cheng <bccheng@google.com>2014-03-25 22:37:19 -0700
committerBen Cheng <bccheng@google.com>2014-03-25 22:37:19 -0700
commit1bc5aee63eb72b341f506ad058502cd0361f0d10 (patch)
treec607e8252f3405424ff15bc2d00aa38dadbb2518 /gcc-4.9/libgo/go/time
parent283a0bf58fcf333c58a2a92c3ebbc41fb9eb1fdb (diff)
downloadtoolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.tar.gz
toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.tar.bz2
toolchain_gcc-1bc5aee63eb72b341f506ad058502cd0361f0d10.zip
Initial checkin of GCC 4.9.0 from trunk (r208799).
Change-Id: I48a3c08bb98542aa215912a75f03c0890e497dba
Diffstat (limited to 'gcc-4.9/libgo/go/time')
-rw-r--r--gcc-4.9/libgo/go/time/example_test.go160
-rw-r--r--gcc-4.9/libgo/go/time/export_test.go24
-rw-r--r--gcc-4.9/libgo/go/time/format.go1244
-rw-r--r--gcc-4.9/libgo/go/time/genzabbrs.go145
-rw-r--r--gcc-4.9/libgo/go/time/internal_test.go80
-rw-r--r--gcc-4.9/libgo/go/time/sleep.go124
-rw-r--r--gcc-4.9/libgo/go/time/sleep_test.go405
-rw-r--r--gcc-4.9/libgo/go/time/sys_plan9.go76
-rw-r--r--gcc-4.9/libgo/go/time/sys_unix.go76
-rw-r--r--gcc-4.9/libgo/go/time/sys_windows.go73
-rw-r--r--gcc-4.9/libgo/go/time/tick.go55
-rw-r--r--gcc-4.9/libgo/go/time/tick_test.go60
-rw-r--r--gcc-4.9/libgo/go/time/time.go1204
-rw-r--r--gcc-4.9/libgo/go/time/time_test.go1526
-rw-r--r--gcc-4.9/libgo/go/time/zoneinfo.go214
-rw-r--r--gcc-4.9/libgo/go/time/zoneinfo_abbrs_windows.go115
-rw-r--r--gcc-4.9/libgo/go/time/zoneinfo_plan9.go160
-rw-r--r--gcc-4.9/libgo/go/time/zoneinfo_read.go343
-rw-r--r--gcc-4.9/libgo/go/time/zoneinfo_unix.go80
-rw-r--r--gcc-4.9/libgo/go/time/zoneinfo_windows.go270
20 files changed, 6434 insertions, 0 deletions
diff --git a/gcc-4.9/libgo/go/time/example_test.go b/gcc-4.9/libgo/go/time/example_test.go
new file mode 100644
index 000000000..cfa5b38c5
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/example_test.go
@@ -0,0 +1,160 @@
+// 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/gcc-4.9/libgo/go/time/export_test.go b/gcc-4.9/libgo/go/time/export_test.go
new file mode 100644
index 000000000..6cd535f6b
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/export_test.go
@@ -0,0 +1,24 @@
+// 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/gcc-4.9/libgo/go/time/format.go b/gcc-4.9/libgo/go/time/format.go
new file mode 100644
index 000000000..6f92c1262
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/format.go
@@ -0,0 +1,1244 @@
+// 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 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: This is the only zone with a lower-case letter.
+ if len(value) >= 4 && value[:4] == "ChST" {
+ 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
+ }
+ return Duration(f), nil
+}
diff --git a/gcc-4.9/libgo/go/time/genzabbrs.go b/gcc-4.9/libgo/go/time/genzabbrs.go
new file mode 100644
index 000000000..7c637cb43
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/genzabbrs.go
@@ -0,0 +1,145 @@
+// 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/gcc-4.9/libgo/go/time/internal_test.go b/gcc-4.9/libgo/go/time/internal_test.go
new file mode 100644
index 000000000..87fdd3216
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/internal_test.go
@@ -0,0 +1,80 @@
+// 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: nano() + (1<<63 - 1),
+ f: empty,
+ arg: nil,
+ }
+ startTimer(r)
+
+ timeout := 100 * Millisecond
+ if runtime.GOOS == "windows" {
+ // Allow more time for gobuilder to succeed.
+ timeout = 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")
+ }
+ runtime.Gosched()
+ }
+ }
+}
diff --git a/gcc-4.9/libgo/go/time/sleep.go b/gcc-4.9/libgo/go/time/sleep.go
new file mode 100644
index 000000000..4f55bebe6
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/sleep.go
@@ -0,0 +1,124 @@
+// 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)
+
+func nano() int64 {
+ sec, nsec := now()
+ return sec*1e9 + int64(nsec)
+}
+
+// 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 nano()
+ }
+ t := nano() + 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) <- Unix(0, 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/gcc-4.9/libgo/go/time/sleep_test.go b/gcc-4.9/libgo/go/time/sleep_test.go
new file mode 100644
index 000000000..cb09a8446
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/sleep_test.go
@@ -0,0 +1,405 @@
+// 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)
+ }
+
+ const batch = 1000
+ P := runtime.GOMAXPROCS(-1)
+ N := int32(b.N / batch)
+
+ b.ResetTimer()
+
+ var wg sync.WaitGroup
+ wg.Add(P)
+
+ for p := 0; p < P; p++ {
+ go func() {
+ for atomic.AddInt32(&N, -1) >= 0 {
+ bench(batch)
+ }
+ wg.Done()
+ }()
+ }
+
+ wg.Wait()
+
+ 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)
+ }
+}
+
+// For gccgo omit 0 for now because it can take too long to start the
+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 timeout = 25 * Millisecond
+ const big = Duration(int64(1<<63 - 1))
+ select {
+ case <-After(big):
+ t.Fatalf("big timeout fired")
+ case <-After(timeout):
+ // OK
+ }
+ const neg = Duration(-1 << 63)
+ select {
+ case <-After(neg):
+ // OK
+ case <-After(timeout):
+ 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 err := CheckRuntimeTimerOverflow(); err != nil {
+ t.Fatalf(err.Error())
+ }
+}
diff --git a/gcc-4.9/libgo/go/time/sys_plan9.go b/gcc-4.9/libgo/go/time/sys_plan9.go
new file mode 100644
index 000000000..848472944
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/sys_plan9.go
@@ -0,0 +1,76 @@
+// 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/gcc-4.9/libgo/go/time/sys_unix.go b/gcc-4.9/libgo/go/time/sys_unix.go
new file mode 100644
index 000000000..60a3ce08f
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/sys_unix.go
@@ -0,0 +1,76 @@
+// 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 netbsd openbsd
+
+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/gcc-4.9/libgo/go/time/sys_windows.go b/gcc-4.9/libgo/go/time/sys_windows.go
new file mode 100644
index 000000000..de63b4bf4
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/sys_windows.go
@@ -0,0 +1,73 @@
+// 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/gcc-4.9/libgo/go/time/tick.go b/gcc-4.9/libgo/go/time/tick.go
new file mode 100644
index 000000000..b92c339c0
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/tick.go
@@ -0,0 +1,55 @@
+// 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.
+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: nano() + int64(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/gcc-4.9/libgo/go/time/tick_test.go b/gcc-4.9/libgo/go/time/tick_test.go
new file mode 100644
index 000000000..d8a086ceb
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/tick_test.go
@@ -0,0 +1,60 @@
+// 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()
+ }
+}
+
+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/gcc-4.9/libgo/go/time/time.go b/gcc-4.9/libgo/go/time/time.go
new file mode 100644
index 000000000..c504df740
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/time.go
@@ -0,0 +1,1204 @@
+// 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 {
+ 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/gcc-4.9/libgo/go/time/time_test.go b/gcc-4.9/libgo/go/time/time_test.go
new file mode 100644
index 000000000..53ae97ea0
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/time_test.go
@@ -0,0 +1,1526 @@
+// 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"
+ "strconv"
+ "strings"
+ "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 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 TestParseInSydney(t *testing.T) {
+ loc, err := LoadLocation("Australia/Sydney")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Check that Parse (and ParseInLocation) understand
+ // that Feb EST and Aug EST are different time zones in Sydney
+ // even though both are called EST.
+ t1, err := ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 EST", loc)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t2 := Date(2013, February, 1, 00, 00, 00, 0, loc)
+ if t1 != t2 {
+ t.Fatalf("ParseInLocation(Feb 01 2013 EST, Sydney) = %v, want %v", t1, t2)
+ }
+ _, offset := t1.Zone()
+ if offset != 11*60*60 {
+ t.Fatalf("ParseInLocation(Feb 01 2013 EST, Sydney).Zone = _, %d, want _, %d", offset, 11*60*60)
+ }
+
+ t1, err = ParseInLocation("Jan 02 2006 MST", "Aug 01 2013 EST", loc)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t2 = Date(2013, August, 1, 00, 00, 00, 0, loc)
+ if t1 != t2 {
+ t.Fatalf("ParseInLocation(Aug 01 2013 EST, Sydney) = %v, want %v", t1, t2)
+ }
+ _, offset = t1.Zone()
+ if offset != 10*60*60 {
+ t.Fatalf("ParseInLocation(Aug 01 2013 EST, Sydney).Zone = _, %d, want _, %d", offset, 10*60*60)
+ }
+}
+
+func TestLoadLocationZipFile(t *testing.T) {
+ t.Skip("gccgo does not use the zip file")
+
+ 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},
+ {"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)
+ }
+}
+
+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},
+}
+
+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)
+ }
+ }
+}
+
+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/gcc-4.9/libgo/go/time/zoneinfo.go b/gcc-4.9/libgo/go/time/zoneinfo.go
new file mode 100644
index 000000000..1c6186258
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/zoneinfo.go
@@ -0,0 +1,214 @@
+// 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
+}
+
+// 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{{-1 << 63, 0, false, false}},
+ cacheStart: -1 << 63,
+ cacheEnd: 1<<63 - 1,
+ }
+ 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.tx) == 0 {
+ name = "UTC"
+ offset = 0
+ isDST = false
+ start = -1 << 63
+ end = 1<<63 - 1
+ 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
+ }
+
+ // Binary search for entry with largest time <= sec.
+ // Not using sort.Search to avoid dependencies.
+ tx := l.tx
+ end = 1<<63 - 1
+ 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
+}
+
+// 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/gcc-4.9/libgo/go/time/zoneinfo_abbrs_windows.go b/gcc-4.9/libgo/go/time/zoneinfo_abbrs_windows.go
new file mode 100644
index 000000000..80334371f
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/zoneinfo_abbrs_windows.go
@@ -0,0 +1,115 @@
+// 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/gcc-4.9/libgo/go/time/zoneinfo_plan9.go b/gcc-4.9/libgo/go/time/zoneinfo_plan9.go
new file mode 100644
index 000000000..0e8f3811b
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/zoneinfo_plan9.go
@@ -0,0 +1,160 @@
+// 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 = 1<<63 - 1
+ 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/gcc-4.9/libgo/go/time/zoneinfo_read.go b/gcc-4.9/libgo/go/time/zoneinfo_read.go
new file mode 100644
index 000000000..7714aa9f5
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/zoneinfo_read.go
@@ -0,0 +1,343 @@
+// 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' {
+ 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, 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: -1 << 63, 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 = 1<<63 - 1
+ 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/gcc-4.9/libgo/go/time/zoneinfo_unix.go b/gcc-4.9/libgo/go/time/zoneinfo_unix.go
new file mode 100644
index 000000000..1a4d115b9
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/zoneinfo_unix.go
@@ -0,0 +1,80 @@
+// 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 netbsd openbsd
+
+// 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() {
+ syscall.Setenv("TZ", "America/Los_Angeles")
+ initLocal()
+}
+
+// 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/gcc-4.9/libgo/go/time/zoneinfo_windows.go b/gcc-4.9/libgo/go/time/zoneinfo_windows.go
new file mode 100644
index 000000000..be4e5c13f
--- /dev/null
+++ b/gcc-4.9/libgo/go/time/zoneinfo_windows.go
@@ -0,0 +1,270 @@
+// 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 {
+ 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 exracts 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 = -1 << 63
+ l.cacheEnd = 1<<63 - 1
+ 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.
+}