Skip to content

Commit 41b9d8c

Browse files
hopehookgopherbot
authored andcommitted
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 <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]>
1 parent aedf298 commit 41b9d8c

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

api/next/50062.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pkg time, method (Time) ZoneBounds() (Time, Time) #50062

src/time/time.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,24 @@ func (t Time) Zone() (name string, offset int) {
11411141
return
11421142
}
11431143

1144+
// ZoneBounds returns the bounds of the time zone in effect at time t.
1145+
// The zone begins at start and the next zone begins at end.
1146+
// If the zone begins at the beginning of time, start will be returned as a zero Time.
1147+
// If the zone goes on forever, end will be returned as a zero Time.
1148+
// The Location of the returned times will be the same as t.
1149+
func (t Time) ZoneBounds() (start, end Time) {
1150+
_, _, startSec, endSec, _ := t.loc.lookup(t.unixSec())
1151+
if startSec != alpha {
1152+
start = unixTime(startSec, 0)
1153+
start.setLoc(t.loc)
1154+
}
1155+
if endSec != omega {
1156+
end = unixTime(endSec, 0)
1157+
end.setLoc(t.loc)
1158+
}
1159+
return
1160+
}
1161+
11441162
// Unix returns t as a Unix time, the number of seconds elapsed
11451163
// since January 1, 1970 UTC. The result does not depend on the
11461164
// location associated with t.

src/time/time_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,3 +1693,77 @@ func TestTimeWithZoneTransition(t *testing.T) {
16931693
}
16941694
}
16951695
}
1696+
1697+
func TestZoneBounds(t *testing.T) {
1698+
undo := DisablePlatformSources()
1699+
defer undo()
1700+
loc, err := LoadLocation("Asia/Shanghai")
1701+
if err != nil {
1702+
t.Fatal(err)
1703+
}
1704+
1705+
// The ZoneBounds of a UTC location would just return two zero Time.
1706+
for _, test := range utctests {
1707+
sec := test.seconds
1708+
golden := &test.golden
1709+
tm := Unix(sec, 0).UTC()
1710+
start, end := tm.ZoneBounds()
1711+
if !(start.IsZero() && end.IsZero()) {
1712+
t.Errorf("ZoneBounds of %+v expects two zero Time, got:\n start=%v\n end=%v", *golden, start, end)
1713+
}
1714+
}
1715+
1716+
// If the zone begins at the beginning of time, start will be returned as a zero Time.
1717+
// Use math.MinInt32 to avoid overflow of int arguments on 32-bit systems.
1718+
beginTime := Date(math.MinInt32, January, 1, 0, 0, 0, 0, loc)
1719+
start, end := beginTime.ZoneBounds()
1720+
if !start.IsZero() || end.IsZero() {
1721+
t.Errorf("ZoneBounds of %v expects start is zero Time, got:\n start=%v\n end=%v", beginTime, start, end)
1722+
}
1723+
1724+
// If the zone goes on forever, end will be returned as a zero Time.
1725+
// Use math.MaxInt32 to avoid overflow of int arguments on 32-bit systems.
1726+
foreverTime := Date(math.MaxInt32, January, 1, 0, 0, 0, 0, loc)
1727+
start, end = foreverTime.ZoneBounds()
1728+
if start.IsZero() || !end.IsZero() {
1729+
t.Errorf("ZoneBounds of %v expects end is zero Time, got:\n start=%v\n end=%v", foreverTime, start, end)
1730+
}
1731+
1732+
// Check some real-world cases to make sure we're getting the right bounds.
1733+
boundOne := Date(1990, September, 16, 1, 0, 0, 0, loc)
1734+
boundTwo := Date(1991, April, 14, 3, 0, 0, 0, loc)
1735+
boundThree := Date(1991, September, 15, 1, 0, 0, 0, loc)
1736+
makeLocalTime := func(sec int64) Time { return Unix(sec, 0) }
1737+
realTests := [...]struct {
1738+
giveTime Time
1739+
wantStart Time
1740+
wantEnd Time
1741+
}{
1742+
// The ZoneBounds of "Asia/Shanghai" Daylight Saving Time
1743+
0: {Date(1991, April, 13, 17, 50, 0, 0, loc), boundOne, boundTwo},
1744+
1: {Date(1991, April, 13, 18, 0, 0, 0, loc), boundOne, boundTwo},
1745+
2: {Date(1991, April, 14, 1, 50, 0, 0, loc), boundOne, boundTwo},
1746+
3: {boundTwo, boundTwo, boundThree},
1747+
4: {Date(1991, September, 14, 16, 50, 0, 0, loc), boundTwo, boundThree},
1748+
5: {Date(1991, September, 14, 17, 0, 0, 0, loc), boundTwo, boundThree},
1749+
6: {Date(1991, September, 15, 0, 50, 0, 0, loc), boundTwo, boundThree},
1750+
1751+
// The ZoneBounds of a local time would return two local Time.
1752+
// Note: We preloaded "America/Los_Angeles" as time.Local for testing
1753+
7: {makeLocalTime(0), makeLocalTime(-5756400), makeLocalTime(9972000)},
1754+
8: {makeLocalTime(1221681866), makeLocalTime(1205056800), makeLocalTime(1225616400)},
1755+
9: {makeLocalTime(2152173599), makeLocalTime(2145916800), makeLocalTime(2152173600)},
1756+
10: {makeLocalTime(2152173600), makeLocalTime(2152173600), makeLocalTime(2172733200)},
1757+
11: {makeLocalTime(2152173601), makeLocalTime(2152173600), makeLocalTime(2172733200)},
1758+
12: {makeLocalTime(2159200800), makeLocalTime(2152173600), makeLocalTime(2172733200)},
1759+
13: {makeLocalTime(2172733199), makeLocalTime(2152173600), makeLocalTime(2172733200)},
1760+
14: {makeLocalTime(2172733200), makeLocalTime(2172733200), makeLocalTime(2177452800)},
1761+
}
1762+
for i, tt := range realTests {
1763+
start, end := tt.giveTime.ZoneBounds()
1764+
if !start.Equal(tt.wantStart) || !end.Equal(tt.wantEnd) {
1765+
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",
1766+
i, tt.giveTime, start, tt.wantStart, end, tt.wantEnd)
1767+
}
1768+
}
1769+
}

0 commit comments

Comments
 (0)