aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8/libgo/go/time
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8/libgo/go/time')
-rw-r--r--gcc-4.8/libgo/go/time/example_test.go43
-rw-r--r--gcc-4.8/libgo/go/time/format.go98
-rw-r--r--gcc-4.8/libgo/go/time/sleep.go25
-rw-r--r--gcc-4.8/libgo/go/time/sleep_test.go25
-rw-r--r--gcc-4.8/libgo/go/time/time_test.go76
-rw-r--r--gcc-4.8/libgo/go/time/zoneinfo.go25
-rw-r--r--gcc-4.8/libgo/go/time/zoneinfo_read.go6
7 files changed, 242 insertions, 56 deletions
diff --git a/gcc-4.8/libgo/go/time/example_test.go b/gcc-4.8/libgo/go/time/example_test.go
index cda565ff3..cfa5b38c5 100644
--- a/gcc-4.8/libgo/go/time/example_test.go
+++ b/gcc-4.8/libgo/go/time/example_test.go
@@ -58,15 +58,52 @@ func ExampleDate() {
}
func ExampleTime_Format() {
- const format = "Jan 2, 2006 at 3:04pm (MST)"
+ // 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(format))
- fmt.Println(t.UTC().Format(format))
+ 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{
diff --git a/gcc-4.8/libgo/go/time/format.go b/gcc-4.8/libgo/go/time/format.go
index 8d21040bf..7fe040231 100644
--- a/gcc-4.8/libgo/go/time/format.go
+++ b/gcc-4.8/libgo/go/time/format.go
@@ -6,15 +6,17 @@ package time
import "errors"
-// These are predefined layouts for use in Time.Format.
-// The standard time used in the layouts is:
+// 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 standard time can be thought of as
+// the reference time can be thought of as
// 01/02 03:04:05PM '06 -0700
-// To define your own format, write down what the standard time would look
+// 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.
+// 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
@@ -367,13 +369,16 @@ func (t Time) String() string {
}
// Format returns a textual representation of the time value formatted
-// according to layout. The layout defines the format by showing the
-// representation of the standard time,
+// according to layout, which defines the format by showing how the reference
+// time,
// Mon Jan 2 15:04:05 -0700 MST 2006
-// which is then used to describe the time to be formatted. Predefined
-// layouts ANSIC, UnixDate, RFC3339 and others describe standard
-// representations. For more information about the formats and the
-// definition of the standard time, see the documentation for ANSIC.
+// 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()
@@ -611,14 +616,14 @@ func skip(value, prefix string) (string, error) {
for len(prefix) > 0 {
if prefix[0] == ' ' {
if len(value) > 0 && value[0] != ' ' {
- return "", errBad
+ return value, errBad
}
prefix = cutspace(prefix)
value = cutspace(value)
continue
}
if len(value) == 0 || value[0] != prefix[0] {
- return "", errBad
+ return value, errBad
}
prefix = prefix[1:]
value = value[1:]
@@ -627,13 +632,15 @@ func skip(value, prefix string) (string, error) {
}
// Parse parses a formatted string and returns the time value it represents.
-// The layout defines the format by showing the representation of the
-// standard time,
+// The layout defines the format by showing how the reference time,
// Mon Jan 2 15:04:05 -0700 MST 2006
-// which is then used to describe the string to be parsed. Predefined layouts
-// ANSIC, UnixDate, RFC3339 and others describe standard representations. For
-// more information about the formats and the definition of the standard
-// time, see the documentation for ANSIC.
+// 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
@@ -641,7 +648,37 @@ func skip(value, prefix string) (string, error) {
// 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?
@@ -892,20 +929,19 @@ func Parse(layout, value string) (Time, error) {
hour = 0
}
- // TODO: be more aggressive checking day?
if z != nil {
return Date(year, Month(month), day, hour, min, sec, nsec, z), nil
}
- t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
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)
+ name, offset, _, _, _ := local.lookup(t.sec + internalToUnix)
if offset == zoneOffset && (zoneName == "" || name == zoneName) {
- t.loc = Local
+ t.loc = local
return t, nil
}
@@ -915,16 +951,14 @@ func Parse(layout, value string) (Time, error) {
}
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)
+ offset, _, ok := local.lookupName(zoneName, t.sec+internalToUnix)
if ok {
- name, off, _, _, _ := Local.lookup(t.sec + internalToUnix - int64(offset))
- if name == zoneName && off == offset {
- t.sec -= int64(offset)
- t.loc = Local
- return t, nil
- }
+ t.sec -= int64(offset)
+ t.loc = local
+ return t, nil
}
// Otherwise, create fake zone with unknown offset.
@@ -932,8 +966,8 @@ func Parse(layout, value string) (Time, error) {
return t, nil
}
- // Otherwise, fall back to UTC.
- return t, nil
+ // Otherwise, fall back to default.
+ return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil
}
func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
diff --git a/gcc-4.8/libgo/go/time/sleep.go b/gcc-4.8/libgo/go/time/sleep.go
index 1e6b4f2e4..591fa27b0 100644
--- a/gcc-4.8/libgo/go/time/sleep.go
+++ b/gcc-4.8/libgo/go/time/sleep.go
@@ -18,10 +18,25 @@ type runtimeTimer struct {
i int32
when int64
period int64
- f func(int64, interface{})
+ 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
@@ -49,7 +64,7 @@ func NewTimer(d Duration) *Timer {
t := &Timer{
C: c,
r: runtimeTimer{
- when: nano() + int64(d),
+ when: when(d),
f: sendTime,
arg: c,
},
@@ -62,9 +77,9 @@ func NewTimer(d Duration) *Timer {
// 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 {
- when := nano() + int64(d)
+ w := when(d)
active := stopTimer(&t.r)
- t.r.when = when
+ t.r.when = w
startTimer(&t.r)
return active
}
@@ -94,7 +109,7 @@ func After(d Duration) <-chan Time {
func AfterFunc(d Duration, f func()) *Timer {
t := &Timer{
r: runtimeTimer{
- when: nano() + int64(d),
+ when: when(d),
f: goFunc,
arg: f,
},
diff --git a/gcc-4.8/libgo/go/time/sleep_test.go b/gcc-4.8/libgo/go/time/sleep_test.go
index e5a9fdf54..762549d3a 100644
--- a/gcc-4.8/libgo/go/time/sleep_test.go
+++ b/gcc-4.8/libgo/go/time/sleep_test.go
@@ -60,10 +60,11 @@ func TestAfterStress(t *testing.T) {
Sleep(Nanosecond)
}
}()
- c := Tick(1)
+ ticker := NewTicker(1)
for i := 0; i < 100; i++ {
- <-c
+ <-ticker.C
}
+ ticker.Stop()
atomic.StoreUint32(&stop, 1)
}
@@ -294,3 +295,23 @@ func TestReset(t *testing.T) {
}
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")
+ }
+}
diff --git a/gcc-4.8/libgo/go/time/time_test.go b/gcc-4.8/libgo/go/time/time_test.go
index a8953aefd..a0ee37ae3 100644
--- a/gcc-4.8/libgo/go/time/time_test.go
+++ b/gcc-4.8/libgo/go/time/time_test.go
@@ -479,6 +479,7 @@ var parseTests = []ParseTest{
{"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},
@@ -534,6 +535,42 @@ func TestParse(t *testing.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)
+ }
+}
+
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.
@@ -640,6 +677,11 @@ var parseErrorTests = []ParseErrorTest{
// 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) {
@@ -1258,23 +1300,33 @@ var mallocTest = []struct {
}
func TestCountMallocs(t *testing.T) {
- defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
+ if runtime.GOMAXPROCS(0) > 1 {
+ t.Skip("skipping; GOMAXPROCS>1")
+ }
for _, mt := range mallocTest {
- const N = 100
- memstats := new(runtime.MemStats)
- runtime.ReadMemStats(memstats)
- mallocs := 0 - memstats.Mallocs
- for i := 0; i < N; i++ {
- mt.fn()
- }
- runtime.ReadMemStats(memstats)
- mallocs += memstats.Mallocs
- if mallocs/N > uint64(mt.count) {
- t.Errorf("%s: expected %d mallocs, got %d", mt.desc, mt.count, mallocs/N)
+ 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)
+ }
+}
+
func BenchmarkNow(b *testing.B) {
for i := 0; i < b.N; i++ {
t = Now()
diff --git a/gcc-4.8/libgo/go/time/zoneinfo.go b/gcc-4.8/libgo/go/time/zoneinfo.go
index 116d34300..c44477f47 100644
--- a/gcc-4.8/libgo/go/time/zoneinfo.go
+++ b/gcc-4.8/libgo/go/time/zoneinfo.go
@@ -145,15 +145,36 @@ func (l *Location) lookup(sec int64) (name string, offset int, isDST bool, start
}
// lookupName returns information about the time zone with
-// the given name (such as "EST").
-func (l *Location) lookupName(name string) (offset int, isDST bool, ok bool) {
+// 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
}
diff --git a/gcc-4.8/libgo/go/time/zoneinfo_read.go b/gcc-4.8/libgo/go/time/zoneinfo_read.go
index a5a2de218..4519c9962 100644
--- a/gcc-4.8/libgo/go/time/zoneinfo_read.go
+++ b/gcc-4.8/libgo/go/time/zoneinfo_read.go
@@ -174,6 +174,12 @@ func loadZoneData(bytes []byte) (l *Location, err error) {
}
}
+ 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}