diff options
author | Ian Lance Taylor <iant@golang.org> | 2017-01-14 00:05:42 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-01-14 00:05:42 +0000 |
commit | c2047754c300b68c05d65faa8dc2925fe67b71b4 (patch) | |
tree | e183ae81a1f48a02945cb6de463a70c5be1b06f6 /libgo/go/time | |
parent | 829afb8f05602bb31c9c597b24df7377fed4f059 (diff) | |
download | gcc-c2047754c300b68c05d65faa8dc2925fe67b71b4.zip gcc-c2047754c300b68c05d65faa8dc2925fe67b71b4.tar.gz gcc-c2047754c300b68c05d65faa8dc2925fe67b71b4.tar.bz2 |
libgo: update to Go 1.8 release candidate 1
Compiler changes:
* Change map assignment to use mapassign and assign value directly.
* Change string iteration to use decoderune, faster for ASCII strings.
* Change makeslice to take int, and use makeslice64 for larger values.
* Add new noverflow field to hmap struct used for maps.
Unresolved problems, to be fixed later:
* Commented out test in go/types/sizes_test.go that doesn't compile.
* Commented out reflect.TestStructOf test for padding after zero-sized field.
Reviewed-on: https://go-review.googlesource.com/35231
gotools/:
Updates for Go 1.8rc1.
* Makefile.am (go_cmd_go_files): Add bug.go.
(s-zdefaultcc): Write defaultPkgConfig.
* Makefile.in: Rebuild.
From-SVN: r244456
Diffstat (limited to 'libgo/go/time')
-rw-r--r-- | libgo/go/time/example_test.go | 18 | ||||
-rw-r--r-- | libgo/go/time/export_android_test.go | 12 | ||||
-rw-r--r-- | libgo/go/time/format.go | 62 | ||||
-rw-r--r-- | libgo/go/time/format_test.go | 4 | ||||
-rw-r--r-- | libgo/go/time/sleep.go | 28 | ||||
-rw-r--r-- | libgo/go/time/time.go | 77 | ||||
-rw-r--r-- | libgo/go/time/time_test.go | 139 | ||||
-rw-r--r-- | libgo/go/time/zoneinfo.go | 2 | ||||
-rw-r--r-- | libgo/go/time/zoneinfo_abbrs_windows.go | 183 | ||||
-rw-r--r-- | libgo/go/time/zoneinfo_android.go | 119 | ||||
-rw-r--r-- | libgo/go/time/zoneinfo_android_test.go | 18 | ||||
-rw-r--r-- | libgo/go/time/zoneinfo_unix.go | 2 | ||||
-rw-r--r-- | libgo/go/time/zoneinfo_windows.go | 2 |
13 files changed, 530 insertions, 136 deletions
diff --git a/libgo/go/time/example_test.go b/libgo/go/time/example_test.go index 4170d51..7dc2bb5 100644 --- a/libgo/go/time/example_test.go +++ b/libgo/go/time/example_test.go @@ -251,20 +251,18 @@ func ExampleTime_Truncate() { 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")) + fmt.Printf("t.Truncate(%5s) = %s\n", d, t.Truncate(d).Format("15:04:05.999999999")) } // Output: - // t.Truncate( 1ns) = 12:15:30.918273645 - // t.Truncate( 1µs) = 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 + // t.Truncate( 1ns) = 12:15:30.918273645 + // t.Truncate( 1µs) = 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 } diff --git a/libgo/go/time/export_android_test.go b/libgo/go/time/export_android_test.go new file mode 100644 index 0000000..fa6a058 --- /dev/null +++ b/libgo/go/time/export_android_test.go @@ -0,0 +1,12 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package time + +func ForceAndroidTzdataForTest(tzdata bool) { + tzdataPaths = origTzdataPaths + if tzdata { + tzdataPaths = tzdataPaths[:1] + } +} diff --git a/libgo/go/time/format.go b/libgo/go/time/format.go index c2ae793..b903e14 100644 --- a/libgo/go/time/format.go +++ b/libgo/go/time/format.go @@ -42,6 +42,13 @@ import "errors" // Z07:00 Z or ±hh:mm // Z07 Z or ±hh // +// The recognized day of week formats are "Mon" and "Monday". +// The recognized month formats are "Jan" and "January". +// +// Text in the format string that is not recognized as part of the reference +// time is echoed verbatim during Format and expected to appear verbatim +// in the input to Parse. +// // The executable example for time.Format demonstrates the working // of the layout string in detail and is a good reference. // @@ -844,6 +851,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) sec, value, err = getnum(value, std == stdZeroSecond) if sec < 0 || 60 <= sec { rangeErrString = "second" + break } // Special case: do we have a fractional second but no // fractional second in the format? @@ -1004,7 +1012,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) } // Validate the day of the month. - if day > daysIn(Month(month), year) { + if day < 1 || day > daysIn(Month(month), year) { return Time{}, &ParseError{alayout, avalue, "", value, ": day out of range"} } @@ -1020,12 +1028,12 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) // 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 + t.setLoc(local) return t, nil } // Otherwise create fake zone to record offset. - t.loc = FixedZone(zoneName, zoneOffset) + t.setLoc(FixedZone(zoneName, zoneOffset)) return t, nil } @@ -1036,7 +1044,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) offset, _, ok := local.lookupName(zoneName, t.sec+internalToUnix) if ok { t.sec -= int64(offset) - t.loc = local + t.setLoc(local) return t, nil } @@ -1045,7 +1053,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) offset, _ = atoi(zoneName[3:]) // Guaranteed OK by parseGMT. offset *= 3600 } - t.loc = FixedZone(zoneName, offset) + t.setLoc(FixedZone(zoneName, offset)) return t, nil } @@ -1093,8 +1101,9 @@ func parseTimeZone(value string) (length int, ok bool) { if value[4] == 'T' { return 5, true } - case 4: // Must end in T to match. - if value[3] == 'T' { + case 4: + // Must end in T, except one special case. + if value[3] == 'T' || value[:4] == "WITA" { return 4, true } case 3: @@ -1173,6 +1182,37 @@ func leadingInt(s string) (x int64, rem string, err error) { return x, s[i:], nil } +// leadingFraction consumes the leading [0-9]* from s. +// It is used only for fractions, so does not return an error on overflow, +// it just stops accumulating precision. +func leadingFraction(s string) (x int64, scale float64, rem string) { + i := 0 + scale = 1 + overflow := false + for ; i < len(s); i++ { + c := s[i] + if c < '0' || c > '9' { + break + } + if overflow { + continue + } + if x > (1<<63-1)/10 { + // It's possible for overflow to give a positive number, so take care. + overflow = true + continue + } + y := x*10 + int64(c) - '0' + if y < 0 { + overflow = true + continue + } + x = y + scale *= 10 + } + return x, scale, s[i:] +} + var unitMap = map[string]int64{ "ns": int64(Nanosecond), "us": int64(Microsecond), @@ -1235,13 +1275,7 @@ func ParseDuration(s string) (Duration, error) { if s != "" && s[0] == '.' { s = s[1:] pl := len(s) - f, s, err = leadingInt(s) - if err != nil { - return 0, errors.New("time: invalid duration " + orig) - } - for n := pl - len(s); n > 0; n-- { - scale *= 10 - } + f, scale, s = leadingFraction(s) post = pl != len(s) } if !pre && !post { diff --git a/libgo/go/time/format_test.go b/libgo/go/time/format_test.go index ed5509b3..648ead0 100644 --- a/libgo/go/time/format_test.go +++ b/libgo/go/time/format_test.go @@ -224,6 +224,7 @@ var dayOutOfRangeTests = []struct { {"Thu Nov 31 21:00:57 2010", false}, {"Thu Dec 31 21:00:57 2010", true}, {"Thu Dec 32 21:00:57 2010", false}, + {"Thu Dec 00 21:00:57 2010", false}, } func TestParseDayOutOfRange(t *testing.T) { @@ -406,6 +407,7 @@ var parseTimeZoneTests = []ParseTimeZoneTest{ {"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. + {"WITA hi", 4, true}, // Issue #18251 } func TestParseTimeZone(t *testing.T) { @@ -442,6 +444,8 @@ var parseErrorTests = []ParseErrorTest{ {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`}, + // invalid second followed by optional fractional seconds + {RFC3339, "2010-02-04T21:00:67.012345678-08:00", "second out of range"}, } func TestParseErrors(t *testing.T) { diff --git a/libgo/go/time/sleep.go b/libgo/go/time/sleep.go index 73114f5..4b01404 100644 --- a/libgo/go/time/sleep.go +++ b/libgo/go/time/sleep.go @@ -12,7 +12,7 @@ func Sleep(d Duration) func runtimeNano() int64 // Interface to timers implemented in package runtime. -// Must be in sync with ../runtime/runtime.h:/^struct.Timer$ +// Must be in sync with ../runtime/time.go:/^type timer type runtimeTimer struct { i int when int64 @@ -55,13 +55,22 @@ type Timer struct { // Stop does not close the channel, to prevent a read from the channel succeeding // incorrectly. // -// To prevent the timer firing after a call to Stop, -// check the return value and drain the channel. For example: +// To prevent a timer created with NewTimer from firing after a call to Stop, +// check the return value and drain the channel. +// For example, assuming the program has not received from t.C already: +// // if !t.Stop() { // <-t.C // } +// // This cannot be done concurrent to other receives from the Timer's // channel. +// +// For a timer created with AfterFunc(d, f), if t.Stop returns false, then the timer +// has already expired and the function f has been started in its own goroutine; +// Stop does not wait for f to complete before returning. +// If the caller needs to know whether f is completed, it must coordinate +// with f explicitly. func (t *Timer) Stop() bool { if t.r.f == nil { panic("time: Stop called on uninitialized Timer") @@ -89,18 +98,25 @@ func NewTimer(d Duration) *Timer { // It returns true if the timer had been active, false if the timer had // expired or been stopped. // -// To reuse an active timer, always call its Stop method first and—if it had -// expired—drain the value from its channel. For example: +// Resetting a timer must take care not to race with the send into t.C +// that happens when the current timer expires. +// If a program has already received a value from t.C, the timer is known +// to have expired, and t.Reset can be used directly. +// If a program has not yet received a value from t.C, however, +// the timer must be stopped and—if Stop reports that the timer expired +// before being stopped—the channel explicitly drained: +// // if !t.Stop() { // <-t.C // } // t.Reset(d) +// // This should not be done concurrent to other receives from the Timer's // channel. // // Note that it is not possible to use Reset's return value correctly, as there // is a race condition between draining the channel and the new timer expiring. -// Reset should always be used in concert with Stop, as described above. +// Reset should always be invoked on stopped or expired channels, as described above. // The return value exists to preserve compatibility with existing programs. func (t *Timer) Reset(d Duration) bool { if t.r.f == nil { diff --git a/libgo/go/time/time.go b/libgo/go/time/time.go index c31de35..10b3246 100644 --- a/libgo/go/time/time.go +++ b/libgo/go/time/time.go @@ -4,7 +4,8 @@ // Package time provides functionality for measuring and displaying time. // -// The calendrical calculations always assume a Gregorian calendar. +// The calendrical calculations always assume a Gregorian calendar, with +// no leap seconds. package time import "errors" @@ -49,11 +50,18 @@ type Time struct { // 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. + // The nil location means UTC. + // All UTC times are represented with loc==nil, never loc==&utcLoc. loc *Location } +func (t *Time) setLoc(loc *Location) { + if loc == &utcLoc { + loc = nil + } + t.loc = loc +} + // 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 @@ -67,8 +75,7 @@ func (t Time) Before(u Time) bool { // 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. +// Do not use == with Time values. func (t Time) Equal(u Time) bool { return t.sec == u.sec && t.nsec == u.nsec } @@ -107,7 +114,14 @@ var months = [...]string{ } // String returns the English name of the month ("January", "February", ...). -func (m Month) String() string { return months[m-1] } +func (m Month) String() string { + if January <= m && m <= December { + return months[m-1] + } + buf := make([]byte, 20) + n := fmtInt(buf, uint64(m)) + return "%!Month(" + string(buf[n:]) + ")" +} // A Weekday specifies a day of the week (Sunday = 0, ...). type Weekday int @@ -585,21 +599,21 @@ func (d Duration) Nanoseconds() int64 { return int64(d) } func (d Duration) Seconds() float64 { sec := d / Second nsec := d % Second - return float64(sec) + float64(nsec)*1e-9 + return float64(sec) + float64(nsec)/1e9 } // 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) + return float64(min) + float64(nsec)/(60*1e9) } // 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) + return float64(hour) + float64(nsec)/(60*60*1e9) } // Add returns the time t+d. @@ -640,6 +654,12 @@ func Since(t Time) Duration { return Now().Sub(t) } +// Until returns the duration until t. +// It is shorthand for t.Sub(time.Now()). +func Until(t Time) Duration { + return t.Sub(Now()) +} + // 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 @@ -651,7 +671,7 @@ func Since(t Time) Duration { 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) + return Date(year+years, month+Month(months), day+days, hour, min, sec, int(t.nsec), t.Location()) } const ( @@ -781,13 +801,13 @@ func Now() Time { // UTC returns t with the location set to UTC. func (t Time) UTC() Time { - t.loc = UTC + t.setLoc(&utcLoc) return t } // Local returns t with the location set to local time. func (t Time) Local() Time { - t.loc = Local + t.setLoc(Local) return t } @@ -798,7 +818,7 @@ func (t Time) In(loc *Location) Time { if loc == nil { panic("time: missing Location in call to Time.In") } - t.loc = loc + t.setLoc(loc) return t } @@ -826,8 +846,9 @@ func (t Time) Unix() int64 { // 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. +// in nanoseconds cannot be represented by an int64 (a date before the year +// 1678 or after 2262). 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) } @@ -838,7 +859,7 @@ const timeBinaryVersion byte = 1 func (t Time) MarshalBinary() ([]byte, error) { var offsetMin int16 // minutes east of UTC. -1 is UTC. - if t.Location() == &utcLoc { + if t.Location() == UTC { offsetMin = -1 } else { _, offset := t.Zone() @@ -899,11 +920,11 @@ func (t *Time) UnmarshalBinary(data []byte) error { offset := int(int16(buf[1])|int16(buf[0])<<8) * 60 if offset == -1*60 { - t.loc = &utcLoc + t.setLoc(&utcLoc) } else if _, localoff, _, _, _ := Local.lookup(t.sec + internalToUnix); offset == localoff { - t.loc = Local + t.setLoc(Local) } else { - t.loc = FixedZone("", offset) + t.setLoc(FixedZone("", offset)) } return nil @@ -942,6 +963,10 @@ func (t Time) MarshalJSON() ([]byte, error) { // 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) error { + // Ignore null, like in the main JSON package. + if string(data) == "null" { + return nil + } // Fractional seconds are handled implicitly by Parse. var err error *t, err = Parse(`"`+RFC3339+`"`, string(data)) @@ -1092,11 +1117,18 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T unix -= int64(offset) } - return Time{unix + unixToInternal, int32(nsec), loc} + t := Time{unix + unixToInternal, int32(nsec), nil} + t.setLoc(loc) + return t } // Truncate returns the result of rounding t down to a multiple of d (since the zero time). // If d <= 0, Truncate returns t unchanged. +// +// Truncate operates on the time as an absolute duration since the +// zero time; it does not operate on the presentation form of the +// time. Thus, Truncate(Hour) may return a time with a non-zero +// minute, depending on the time's Location. func (t Time) Truncate(d Duration) Time { if d <= 0 { return t @@ -1108,6 +1140,11 @@ func (t Time) Truncate(d Duration) Time { // 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. +// +// Round operates on the time as an absolute duration since the +// zero time; it does not operate on the presentation form of the +// time. Thus, Round(Hour) may return a time with a non-zero +// minute, depending on the time's Location. func (t Time) Round(d Duration) Time { if d <= 0 { return t diff --git a/libgo/go/time/time_test.go b/libgo/go/time/time_test.go index c9665ea..2922560 100644 --- a/libgo/go/time/time_test.go +++ b/libgo/go/time/time_test.go @@ -840,6 +840,10 @@ var parseDurationTests = []struct { {"9223372036s854ms775us807ns", true, (1<<63 - 1) * Nanosecond}, // large negative value {"-9223372036854775807ns", true, -1<<63 + 1*Nanosecond}, + // huge string; issue 15011. + {"0.100000000000000000000h", true, 6 * Minute}, + // This value tests the first overflow check in leadingFraction. + {"0.830103483285477580700h", true, 49*Minute + 48*Second + 372539827*Nanosecond}, // errors {"", false, 0}, @@ -891,7 +895,7 @@ func TestLocationRace(t *testing.T) { go func() { c <- Now().String() }() - Now().String() + _ = Now().String() <-c Sleep(100 * Millisecond) @@ -999,6 +1003,21 @@ func TestDurationNanoseconds(t *testing.T) { } } +var secDurationTests = []struct { + d Duration + want float64 +}{ + {Duration(300000000), 0.3}, +} + +func TestDurationSeconds(t *testing.T) { + for _, tt := range secDurationTests { + if got := tt.d.Seconds(); got != tt.want { + t.Errorf("d.Seconds() = %g; want: %g", got, tt.want) + } + } +} + var minDurationTests = []struct { d Duration want float64 @@ -1007,6 +1026,7 @@ var minDurationTests = []struct { {Duration(-1), -1 / 60e9}, {Duration(1), 1 / 60e9}, {Duration(60000000000), 1}, + {Duration(3000), 5e-8}, } func TestDurationMinutes(t *testing.T) { @@ -1025,6 +1045,7 @@ var hourDurationTests = []struct { {Duration(-1), -1 / 3600e9}, {Duration(1), 1 / 3600e9}, {Duration(3600000000000), 1}, + {Duration(36), 1e-11}, } func TestDurationHours(t *testing.T) { @@ -1035,6 +1056,100 @@ func TestDurationHours(t *testing.T) { } } +var defaultLocTests = []struct { + name string + f func(t1, t2 Time) bool +}{ + {"After", func(t1, t2 Time) bool { return t1.After(t2) == t2.After(t1) }}, + {"Before", func(t1, t2 Time) bool { return t1.Before(t2) == t2.Before(t1) }}, + {"Equal", func(t1, t2 Time) bool { return t1.Equal(t2) == t2.Equal(t1) }}, + + {"IsZero", func(t1, t2 Time) bool { return t1.IsZero() == t2.IsZero() }}, + {"Date", func(t1, t2 Time) bool { + a1, b1, c1 := t1.Date() + a2, b2, c2 := t2.Date() + return a1 == a2 && b1 == b2 && c1 == c2 + }}, + {"Year", func(t1, t2 Time) bool { return t1.Year() == t2.Year() }}, + {"Month", func(t1, t2 Time) bool { return t1.Month() == t2.Month() }}, + {"Day", func(t1, t2 Time) bool { return t1.Day() == t2.Day() }}, + {"Weekday", func(t1, t2 Time) bool { return t1.Weekday() == t2.Weekday() }}, + {"ISOWeek", func(t1, t2 Time) bool { + a1, b1 := t1.ISOWeek() + a2, b2 := t2.ISOWeek() + return a1 == a2 && b1 == b2 + }}, + {"Clock", func(t1, t2 Time) bool { + a1, b1, c1 := t1.Clock() + a2, b2, c2 := t2.Clock() + return a1 == a2 && b1 == b2 && c1 == c2 + }}, + {"Hour", func(t1, t2 Time) bool { return t1.Hour() == t2.Hour() }}, + {"Minute", func(t1, t2 Time) bool { return t1.Minute() == t2.Minute() }}, + {"Second", func(t1, t2 Time) bool { return t1.Second() == t2.Second() }}, + {"Nanosecond", func(t1, t2 Time) bool { return t1.Hour() == t2.Hour() }}, + {"YearDay", func(t1, t2 Time) bool { return t1.YearDay() == t2.YearDay() }}, + + // Using Equal since Add don't modify loc using "==" will cause a fail + {"Add", func(t1, t2 Time) bool { return t1.Add(Hour).Equal(t2.Add(Hour)) }}, + {"Sub", func(t1, t2 Time) bool { return t1.Sub(t2) == t2.Sub(t1) }}, + + //Original caus for this test case bug 15852 + {"AddDate", func(t1, t2 Time) bool { return t1.AddDate(1991, 9, 3) == t2.AddDate(1991, 9, 3) }}, + + {"UTC", func(t1, t2 Time) bool { return t1.UTC() == t2.UTC() }}, + {"Local", func(t1, t2 Time) bool { return t1.Local() == t2.Local() }}, + {"In", func(t1, t2 Time) bool { return t1.In(UTC) == t2.In(UTC) }}, + + {"Local", func(t1, t2 Time) bool { return t1.Local() == t2.Local() }}, + {"Zone", func(t1, t2 Time) bool { + a1, b1 := t1.Zone() + a2, b2 := t2.Zone() + return a1 == a2 && b1 == b2 + }}, + + {"Unix", func(t1, t2 Time) bool { return t1.Unix() == t2.Unix() }}, + {"UnixNano", func(t1, t2 Time) bool { return t1.UnixNano() == t2.UnixNano() }}, + + {"MarshalBinary", func(t1, t2 Time) bool { + a1, b1 := t1.MarshalBinary() + a2, b2 := t2.MarshalBinary() + return bytes.Equal(a1, a2) && b1 == b2 + }}, + {"GobEncode", func(t1, t2 Time) bool { + a1, b1 := t1.GobEncode() + a2, b2 := t2.GobEncode() + return bytes.Equal(a1, a2) && b1 == b2 + }}, + {"MarshalJSON", func(t1, t2 Time) bool { + a1, b1 := t1.MarshalJSON() + a2, b2 := t2.MarshalJSON() + return bytes.Equal(a1, a2) && b1 == b2 + }}, + {"MarshalText", func(t1, t2 Time) bool { + a1, b1 := t1.MarshalText() + a2, b2 := t2.MarshalText() + return bytes.Equal(a1, a2) && b1 == b2 + }}, + + {"Truncate", func(t1, t2 Time) bool { return t1.Truncate(Hour).Equal(t2.Truncate(Hour)) }}, + {"Round", func(t1, t2 Time) bool { return t1.Round(Hour).Equal(t2.Round(Hour)) }}, + + {"== Time{}", func(t1, t2 Time) bool { return (t1 == Time{}) == (t2 == Time{}) }}, +} + +func TestDefaultLoc(t *testing.T) { + //This test verifyes that all Time's methods behaves identical if loc is set + //as nil or UTC + for _, tt := range defaultLocTests { + t1 := Time{} + t2 := Time{}.UTC() + if !tt.f(t1, t2) { + t.Errorf("Time{} and Time{}.UTC() behave differently for %s", tt.name) + } + } +} + func BenchmarkNow(b *testing.B) { for i := 0; i < b.N; i++ { t = Now() @@ -1117,3 +1232,25 @@ func BenchmarkDay(b *testing.B) { _ = t.Day() } } + +func TestMarshalBinaryZeroTime(t *testing.T) { + t0 := Time{} + enc, err := t0.MarshalBinary() + if err != nil { + t.Fatal(err) + } + t1 := Now() // not zero + if err := t1.UnmarshalBinary(enc); err != nil { + t.Fatal(err) + } + if t1 != t0 { + t.Errorf("t0=%#v\nt1=%#v\nwant identical structures", t0, t1) + } +} + +// Issue 17720: Zero value of time.Month fails to print +func TestZeroMonthString(t *testing.T) { + if got, want := Month(0).String(), "%!Month(0)"; got != want { + t.Errorf("zero month = %q; want %q", got, want) + } +} diff --git a/libgo/go/time/zoneinfo.go b/libgo/go/time/zoneinfo.go index c567439..fb0aa39 100644 --- a/libgo/go/time/zoneinfo.go +++ b/libgo/go/time/zoneinfo.go @@ -9,6 +9,8 @@ import ( "syscall" ) +//go:generate env ZONEINFO=$GOROOT/lib/time/zoneinfo.zip go run genzabbrs.go -output zoneinfo_abbrs_windows.go + // 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. diff --git a/libgo/go/time/zoneinfo_abbrs_windows.go b/libgo/go/time/zoneinfo_abbrs_windows.go index 344a891..9425db8 100644 --- a/libgo/go/time/zoneinfo_abbrs_windows.go +++ b/libgo/go/time/zoneinfo_abbrs_windows.go @@ -13,92 +13,106 @@ type abbr struct { } 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 - "Libya Standard Time": {"EET", "EET"}, // Africa/Tripoli - "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", "BRT"}, // America/Bahia - "SA Pacific Standard Time": {"COT", "COT"}, // America/Bogota - "Argentina Standard Time": {"ART", "ART"}, // America/Buenos_Aires - "Eastern Standard Time (Mexico)": {"EST", "EST"}, // America/Cancun - "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", "UYT"}, // 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 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": {"+06", "+06"}, // Asia/Almaty - "Jordan Standard Time": {"EET", "EEST"}, // Asia/Amman - "Arabic Standard Time": {"AST", "AST"}, // Asia/Baghdad - "Azerbaijan Standard Time": {"AZT", "AZT"}, // Asia/Baku - "SE Asia Standard Time": {"ICT", "ICT"}, // Asia/Bangkok - "Altai Standard Time": {"+06", "+07"}, // Asia/Barnaul - "Middle East Standard Time": {"EET", "EEST"}, // Asia/Beirut - "India Standard Time": {"IST", "IST"}, // Asia/Calcutta - "Transbaikal Standard Time": {"IRKT", "YAKT"}, // Asia/Chita - "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 - "Russia Time Zone 11": {"PETT", "PETT"}, // Asia/Kamchatka - "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 - "N. Central Asia Standard Time": {"NOVT", "NOVT"}, // Asia/Novosibirsk - "North Korea Standard Time": {"KST", "KST"}, // Asia/Pyongyang - "Myanmar Standard Time": {"MMT", "MMT"}, // Asia/Rangoon - "Arab Standard Time": {"AST", "AST"}, // Asia/Riyadh - "Sakhalin Standard Time": {"SAKT", "SAKT"}, // Asia/Sakhalin - "Korea Standard Time": {"KST", "KST"}, // Asia/Seoul - "China Standard Time": {"CST", "CST"}, // Asia/Shanghai - "Singapore Standard Time": {"SGT", "SGT"}, // Asia/Singapore - "Russia Time Zone 10": {"SRET", "SRET"}, // Asia/Srednekolymsk - "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", "ULAST"}, // 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": {"ACST", "ACDT"}, // Australia/Adelaide - "E. Australia Standard Time": {"AEST", "AEST"}, // Australia/Brisbane - "AUS Central Standard Time": {"ACST", "ACST"}, // Australia/Darwin - "Tasmania Standard Time": {"AEST", "AEDT"}, // Australia/Hobart - "W. Australia Standard Time": {"AWST", "AWST"}, // Australia/Perth - "AUS Eastern Standard Time": {"AEST", "AEDT"}, // Australia/Sydney + "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 + "Libya Standard Time": {"EET", "EET"}, // Africa/Tripoli + "Namibia Standard Time": {"WAT", "WAST"}, // Africa/Windhoek + "Aleutian Standard Time": {"HST", "HDT"}, // America/Adak + "Alaskan Standard Time": {"AKST", "AKDT"}, // America/Anchorage + "Tocantins Standard Time": {"BRT", "BRT"}, // America/Araguaina + "Paraguay Standard Time": {"PYT", "PYST"}, // America/Asuncion + "Bahia Standard Time": {"BRT", "BRT"}, // America/Bahia + "SA Pacific Standard Time": {"COT", "COT"}, // America/Bogota + "Argentina Standard Time": {"ART", "ART"}, // America/Buenos_Aires + "Eastern Standard Time (Mexico)": {"EST", "EST"}, // America/Cancun + "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 + "Turks And Caicos Standard Time": {"AST", "AST"}, // America/Grand_Turk + "Central America Standard Time": {"CST", "CST"}, // America/Guatemala + "Atlantic Standard Time": {"AST", "ADT"}, // America/Halifax + "Cuba Standard Time": {"CST", "CDT"}, // America/Havana + "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 + "Saint Pierre Standard Time": {"PMST", "PMDT"}, // America/Miquelon + "Montevideo Standard Time": {"UYT", "UYT"}, // America/Montevideo + "Eastern Standard Time": {"EST", "EDT"}, // America/New_York + "US Mountain Standard Time": {"MST", "MST"}, // America/Phoenix + "Haiti Standard Time": {"EST", "EST"}, // America/Port-au-Prince + "Canada Central Standard Time": {"CST", "CST"}, // America/Regina + "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 + "Pacific Standard Time (Mexico)": {"PST", "PDT"}, // America/Tijuana + "Central Asia Standard Time": {"+06", "+06"}, // Asia/Almaty + "Jordan Standard Time": {"EET", "EEST"}, // Asia/Amman + "Arabic Standard Time": {"AST", "AST"}, // Asia/Baghdad + "Azerbaijan Standard Time": {"AZT", "AZT"}, // Asia/Baku + "SE Asia Standard Time": {"ICT", "ICT"}, // Asia/Bangkok + "Altai Standard Time": {"+06", "+07"}, // Asia/Barnaul + "Middle East Standard Time": {"EET", "EEST"}, // Asia/Beirut + "India Standard Time": {"IST", "IST"}, // Asia/Calcutta + "Transbaikal Standard Time": {"IRKT", "YAKT"}, // Asia/Chita + "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 + "West Bank Standard Time": {"EET", "EEST"}, // Asia/Hebron + "W. Mongolia Standard Time": {"HOVT", "HOVST"}, // Asia/Hovd + "North Asia East Standard Time": {"IRKT", "IRKT"}, // Asia/Irkutsk + "Israel Standard Time": {"IST", "IDT"}, // Asia/Jerusalem + "Afghanistan Standard Time": {"AFT", "AFT"}, // Asia/Kabul + "Russia Time Zone 11": {"PETT", "PETT"}, // Asia/Kamchatka + "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 + "N. Central Asia Standard Time": {"+06", "+07"}, // Asia/Novosibirsk + "North Korea Standard Time": {"KST", "KST"}, // Asia/Pyongyang + "Myanmar Standard Time": {"MMT", "MMT"}, // Asia/Rangoon + "Arab Standard Time": {"AST", "AST"}, // Asia/Riyadh + "Sakhalin Standard Time": {"SAKT", "SAKT"}, // Asia/Sakhalin + "Korea Standard Time": {"KST", "KST"}, // Asia/Seoul + "China Standard Time": {"CST", "CST"}, // Asia/Shanghai + "Singapore Standard Time": {"SGT", "SGT"}, // Asia/Singapore + "Russia Time Zone 10": {"SRET", "SRET"}, // Asia/Srednekolymsk + "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 + "Tomsk Standard Time": {"+06", "+07"}, // Asia/Tomsk + "Ulaanbaatar Standard Time": {"ULAT", "ULAST"}, // 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": {"ACST", "ACDT"}, // Australia/Adelaide + "E. Australia Standard Time": {"AEST", "AEST"}, // Australia/Brisbane + "AUS Central Standard Time": {"ACST", "ACST"}, // Australia/Darwin + "Aus Central W. Standard Time": {"ACWST", "ACWST"}, // Australia/Eucla + "Tasmania Standard Time": {"AEST", "AEDT"}, // Australia/Hobart + "Lord Howe Standard Time": {"LHST", "LHDT"}, // Australia/Lord_Howe + "W. Australia Standard Time": {"AWST", "AWST"}, // Australia/Perth + "AUS Eastern Standard Time": {"AEST", "AEDT"}, // 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-08": {"GMT+8", "GMT+8"}, // Etc/GMT+8 + "UTC-09": {"GMT+9", "GMT+9"}, // Etc/GMT+9 "UTC+12": {"GMT-12", "GMT-12"}, // Etc/GMT-12 "Astrakhan Standard Time": {"+03", "+04"}, // Europe/Astrakhan "W. Europe Standard Time": {"CET", "CEST"}, // Europe/Berlin @@ -117,10 +131,15 @@ var abbrs = map[string]abbr{ "Mauritius Standard Time": {"MUT", "MUT"}, // Indian/Mauritius "Samoa Standard Time": {"WSST", "WSDT"}, // Pacific/Apia "New Zealand Standard Time": {"NZST", "NZDT"}, // Pacific/Auckland + "Bougainville Standard Time": {"BST", "BST"}, // Pacific/Bougainville + "Chatham Islands Standard Time": {"CHAST", "CHADT"}, // Pacific/Chatham + "Easter Island Standard Time": {"EAST", "EASST"}, // Pacific/Easter "Fiji Standard Time": {"FJT", "FJST"}, // Pacific/Fiji "Central Pacific Standard Time": {"SBT", "SBT"}, // Pacific/Guadalcanal "Hawaiian Standard Time": {"HST", "HST"}, // Pacific/Honolulu "Line Islands Standard Time": {"LINT", "LINT"}, // Pacific/Kiritimati + "Marquesas Standard Time": {"MART", "MART"}, // Pacific/Marquesas + "Norfolk Standard Time": {"NFT", "NFT"}, // Pacific/Norfolk "West Pacific Standard Time": {"PGT", "PGT"}, // Pacific/Port_Moresby "Tonga Standard Time": {"TOT", "TOT"}, // Pacific/Tongatapu } diff --git a/libgo/go/time/zoneinfo_android.go b/libgo/go/time/zoneinfo_android.go new file mode 100644 index 0000000..695a8ad --- /dev/null +++ b/libgo/go/time/zoneinfo_android.go @@ -0,0 +1,119 @@ +// Copyright 2016 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 the "tzdata" packed timezone file used on Android. +// The format is lifted from ZoneInfoDB.java and ZoneInfo.java in +// java/libcore/util in the AOSP. + +package time + +import ( + "errors" + "runtime" +) + +var tzdataPaths = []string{ + "/system/usr/share/zoneinfo/tzdata", + "/data/misc/zoneinfo/current/tzdata", + runtime.GOROOT() + "/lib/time/zoneinfo.zip", +} + +var origTzdataPaths = tzdataPaths + +func forceZipFileForTesting(zipOnly bool) { + tzdataPaths = make([]string, len(origTzdataPaths)) + copy(tzdataPaths, origTzdataPaths) + if zipOnly { + for i := 0; i < len(tzdataPaths)-1; i++ { + tzdataPaths[i] = "/XXXNOEXIST" + } + } +} + +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() { + // TODO(elias.naur): getprop persist.sys.timezone + localLoc = *UTC +} + +func loadLocation(name string) (*Location, error) { + var firstErr error + for _, path := range tzdataPaths { + var z *Location + var err error + if len(path) > 4 && path[len(path)-4:] == ".zip" { + z, err = loadZoneZip(path, name) + } else { + z, err = loadTzdataFile(path, name) + } + if err == nil { + z.name = name + return z, nil + } else if firstErr == nil && !isNotExist(err) { + firstErr = err + } + } + if firstErr != nil { + return nil, firstErr + } + return nil, errors.New("unknown time zone " + name) +} + +func loadTzdataFile(file, name string) (*Location, error) { + const ( + headersize = 12 + 3*4 + namesize = 40 + entrysize = namesize + 3*4 + ) + if len(name) > namesize { + return nil, errors.New(name + " is longer than the maximum zone name length (40 bytes)") + } + fd, err := open(file) + if err != nil { + return nil, err + } + defer closefd(fd) + + buf := make([]byte, headersize) + if err := preadn(fd, buf, 0); err != nil { + return nil, errors.New("corrupt tzdata file " + file) + } + d := data{buf, false} + if magic := d.read(6); string(magic) != "tzdata" { + return nil, errors.New("corrupt tzdata file " + file) + } + d = data{buf[12:], false} + indexOff, _ := d.big4() + dataOff, _ := d.big4() + indexSize := dataOff - indexOff + entrycount := indexSize / entrysize + buf = make([]byte, indexSize) + if err := preadn(fd, buf, int(indexOff)); err != nil { + return nil, errors.New("corrupt tzdata file " + file) + } + for i := 0; i < int(entrycount); i++ { + entry := buf[i*entrysize : (i+1)*entrysize] + // len(name) <= namesize is checked at function entry + if string(entry[:len(name)]) != name { + continue + } + d := data{entry[namesize:], false} + off, _ := d.big4() + size, _ := d.big4() + buf := make([]byte, size) + if err := preadn(fd, buf, int(off+dataOff)); err != nil { + return nil, errors.New("corrupt tzdata file " + file) + } + return loadZoneData(buf) + } + return nil, errors.New("cannot find " + name + " in tzdata file " + file) +} diff --git a/libgo/go/time/zoneinfo_android_test.go b/libgo/go/time/zoneinfo_android_test.go new file mode 100644 index 0000000..ba065d1 --- /dev/null +++ b/libgo/go/time/zoneinfo_android_test.go @@ -0,0 +1,18 @@ +// Copyright 2016 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 TestAndroidTzdata(t *testing.T) { + ForceAndroidTzdataForTest(true) + defer ForceAndroidTzdataForTest(false) + if _, err := LoadLocation("America/Los_Angeles"); err != nil { + t.Error(err) + } +} diff --git a/libgo/go/time/zoneinfo_unix.go b/libgo/go/time/zoneinfo_unix.go index 6c7aaff..7727488 100644 --- a/libgo/go/time/zoneinfo_unix.go +++ b/libgo/go/time/zoneinfo_unix.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build darwin,386 darwin,amd64 dragonfly freebsd linux nacl netbsd openbsd solaris +// +build darwin,386 darwin,amd64 dragonfly freebsd linux,!android nacl netbsd openbsd solaris // Parse "zoneinfo" time zone file. // This is a fairly standard file format used on OS X, Linux, BSD, Sun, and others. diff --git a/libgo/go/time/zoneinfo_windows.go b/libgo/go/time/zoneinfo_windows.go index a6546f5..a6e227b 100644 --- a/libgo/go/time/zoneinfo_windows.go +++ b/libgo/go/time/zoneinfo_windows.go @@ -11,8 +11,6 @@ import ( "syscall" ) -//go:generate go run genzabbrs.go -output zoneinfo_abbrs_windows.go - // TODO(rsc): Fall back to copy of zoneinfo files. // BUG(brainman,rsc): On Windows, the operating system does not provide complete |