mirror of
https://github.com/golang/go
synced 2024-11-02 11:21:19 +00:00
time: add Time.ZoneBounds
The method Location.lookup returns the "start" and "end" times bracketing seconds when that zone is in effect. This CL does these things: 1. Exported the "start" and "end" times as time.Time form 2. Keep the "Location" of the returned times be the same as underlying time Fixes #50062. Change-Id: I88888a100d0fc68f4984a85c75a85a83aa3e5d80 Reviewed-on: https://go-review.googlesource.com/c/go/+/405374 Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: Ian Lance Taylor <iant@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
aedf298daf
commit
41b9d8c75e
3 changed files with 93 additions and 0 deletions
1
api/next/50062.txt
Normal file
1
api/next/50062.txt
Normal file
|
@ -0,0 +1 @@
|
|||
pkg time, method (Time) ZoneBounds() (Time, Time) #50062
|
|
@ -1141,6 +1141,24 @@ func (t Time) Zone() (name string, offset int) {
|
|||
return
|
||||
}
|
||||
|
||||
// ZoneBounds returns the bounds of the time zone in effect at time t.
|
||||
// The zone begins at start and the next zone begins at end.
|
||||
// If the zone begins at the beginning of time, start will be returned as a zero Time.
|
||||
// If the zone goes on forever, end will be returned as a zero Time.
|
||||
// The Location of the returned times will be the same as t.
|
||||
func (t Time) ZoneBounds() (start, end Time) {
|
||||
_, _, startSec, endSec, _ := t.loc.lookup(t.unixSec())
|
||||
if startSec != alpha {
|
||||
start = unixTime(startSec, 0)
|
||||
start.setLoc(t.loc)
|
||||
}
|
||||
if endSec != omega {
|
||||
end = unixTime(endSec, 0)
|
||||
end.setLoc(t.loc)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Unix returns t as a Unix time, the number of seconds elapsed
|
||||
// since January 1, 1970 UTC. The result does not depend on the
|
||||
// location associated with t.
|
||||
|
|
|
@ -1693,3 +1693,77 @@ func TestTimeWithZoneTransition(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestZoneBounds(t *testing.T) {
|
||||
undo := DisablePlatformSources()
|
||||
defer undo()
|
||||
loc, err := LoadLocation("Asia/Shanghai")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// The ZoneBounds of a UTC location would just return two zero Time.
|
||||
for _, test := range utctests {
|
||||
sec := test.seconds
|
||||
golden := &test.golden
|
||||
tm := Unix(sec, 0).UTC()
|
||||
start, end := tm.ZoneBounds()
|
||||
if !(start.IsZero() && end.IsZero()) {
|
||||
t.Errorf("ZoneBounds of %+v expects two zero Time, got:\n start=%v\n end=%v", *golden, start, end)
|
||||
}
|
||||
}
|
||||
|
||||
// If the zone begins at the beginning of time, start will be returned as a zero Time.
|
||||
// Use math.MinInt32 to avoid overflow of int arguments on 32-bit systems.
|
||||
beginTime := Date(math.MinInt32, January, 1, 0, 0, 0, 0, loc)
|
||||
start, end := beginTime.ZoneBounds()
|
||||
if !start.IsZero() || end.IsZero() {
|
||||
t.Errorf("ZoneBounds of %v expects start is zero Time, got:\n start=%v\n end=%v", beginTime, start, end)
|
||||
}
|
||||
|
||||
// If the zone goes on forever, end will be returned as a zero Time.
|
||||
// Use math.MaxInt32 to avoid overflow of int arguments on 32-bit systems.
|
||||
foreverTime := Date(math.MaxInt32, January, 1, 0, 0, 0, 0, loc)
|
||||
start, end = foreverTime.ZoneBounds()
|
||||
if start.IsZero() || !end.IsZero() {
|
||||
t.Errorf("ZoneBounds of %v expects end is zero Time, got:\n start=%v\n end=%v", foreverTime, start, end)
|
||||
}
|
||||
|
||||
// Check some real-world cases to make sure we're getting the right bounds.
|
||||
boundOne := Date(1990, September, 16, 1, 0, 0, 0, loc)
|
||||
boundTwo := Date(1991, April, 14, 3, 0, 0, 0, loc)
|
||||
boundThree := Date(1991, September, 15, 1, 0, 0, 0, loc)
|
||||
makeLocalTime := func(sec int64) Time { return Unix(sec, 0) }
|
||||
realTests := [...]struct {
|
||||
giveTime Time
|
||||
wantStart Time
|
||||
wantEnd Time
|
||||
}{
|
||||
// The ZoneBounds of "Asia/Shanghai" Daylight Saving Time
|
||||
0: {Date(1991, April, 13, 17, 50, 0, 0, loc), boundOne, boundTwo},
|
||||
1: {Date(1991, April, 13, 18, 0, 0, 0, loc), boundOne, boundTwo},
|
||||
2: {Date(1991, April, 14, 1, 50, 0, 0, loc), boundOne, boundTwo},
|
||||
3: {boundTwo, boundTwo, boundThree},
|
||||
4: {Date(1991, September, 14, 16, 50, 0, 0, loc), boundTwo, boundThree},
|
||||
5: {Date(1991, September, 14, 17, 0, 0, 0, loc), boundTwo, boundThree},
|
||||
6: {Date(1991, September, 15, 0, 50, 0, 0, loc), boundTwo, boundThree},
|
||||
|
||||
// The ZoneBounds of a local time would return two local Time.
|
||||
// Note: We preloaded "America/Los_Angeles" as time.Local for testing
|
||||
7: {makeLocalTime(0), makeLocalTime(-5756400), makeLocalTime(9972000)},
|
||||
8: {makeLocalTime(1221681866), makeLocalTime(1205056800), makeLocalTime(1225616400)},
|
||||
9: {makeLocalTime(2152173599), makeLocalTime(2145916800), makeLocalTime(2152173600)},
|
||||
10: {makeLocalTime(2152173600), makeLocalTime(2152173600), makeLocalTime(2172733200)},
|
||||
11: {makeLocalTime(2152173601), makeLocalTime(2152173600), makeLocalTime(2172733200)},
|
||||
12: {makeLocalTime(2159200800), makeLocalTime(2152173600), makeLocalTime(2172733200)},
|
||||
13: {makeLocalTime(2172733199), makeLocalTime(2152173600), makeLocalTime(2172733200)},
|
||||
14: {makeLocalTime(2172733200), makeLocalTime(2172733200), makeLocalTime(2177452800)},
|
||||
}
|
||||
for i, tt := range realTests {
|
||||
start, end := tt.giveTime.ZoneBounds()
|
||||
if !start.Equal(tt.wantStart) || !end.Equal(tt.wantEnd) {
|
||||
t.Errorf("#%d:: ZoneBounds of %v expects right bounds:\n got start=%v\n want start=%v\n got end=%v\n want end=%v",
|
||||
i, tt.giveTime, start, tt.wantStart, end, tt.wantEnd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue