]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.17] time: fix looking for zone offset when date is close to a...
authorzhouguangyuan <zhouguangyuan.xian@gmail.com>
Tue, 2 Nov 2021 15:17:21 +0000 (23:17 +0800)
committerIan Lance Taylor <iant@golang.org>
Mon, 29 Nov 2021 19:46:17 +0000 (19:46 +0000)
The old implement passed start - 1 or end in func lookup to adjust the offset.But if the time is close to the last zoneTrans, like the issue, testcase and comment, the "start" from lookup will be omega. It can't be adjusted correctly.

Fixes #49407

Change-Id: Ibaf82dc4db6d5dd3279796f003d2b19c38a26341
Reviewed-on: https://go-review.googlesource.com/c/go/+/360616
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Robert Findley <rfindley@google.com>
(cherry picked from commit 90462dfc3aa99649de90bb587af56a9cb0214665)
Reviewed-on: https://go-review.googlesource.com/c/go/+/361955
Trust: Dmitri Shuralyov <dmitshur@golang.org>

src/time/time.go
src/time/time_test.go

index 4ecc3d82dcc95895742e6219c95503c994722c0f..a7d06cdef3fc06c2ab4c6140759d0c5f8235f8b7 100644 (file)
@@ -1416,17 +1416,17 @@ func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) T
 
        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
+       // Look for zone offset for expected time, so we can adjust to UTC.
+       // The lookup function expects UTC, so first we pass unix 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)
+               utc := unix - int64(offset)
+               // If utc is valid for the time zone we found, then we have the right offset.
+               // If not, we get the correct offset by looking up utc in the location.
+               if utc < start || utc >= end {
+                       _, offset, _, _, _ = loc.lookup(utc)
                }
                unix -= int64(offset)
        }
index cea5f2d3f5acebcd18214e0167bf6a2a8de9f5d7..906ceb8defb0660d592bc6d0cf93e1de8a93f0c2 100644 (file)
@@ -1569,3 +1569,45 @@ func TestTimeAddSecOverflow(t *testing.T) {
                }
        }
 }
+
+// Issue 49284: time: ParseInLocation incorrectly because of Daylight Saving Time
+func TestTimeWithZoneTransition(t *testing.T) {
+       ForceZipFileForTesting(true)
+       defer ForceZipFileForTesting(false)
+
+       loc, err := LoadLocation("Asia/Shanghai")
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       tests := [...]struct {
+               give Time
+               want Time
+       }{
+               // 14 Apr 1991 - Daylight Saving Time Started
+               // When time of "Asia/Shanghai" was about to reach
+               // Sunday, 14 April 1991, 02:00:00 clocks were turned forward 1 hour to
+               // Sunday, 14 April 1991, 03:00:00 local daylight time instead.
+               // The UTC time was 13 April 1991, 18:00:00
+               0: {Date(1991, April, 13, 17, 50, 0, 0, loc), Date(1991, April, 13, 9, 50, 0, 0, UTC)},
+               1: {Date(1991, April, 13, 18, 0, 0, 0, loc), Date(1991, April, 13, 10, 0, 0, 0, UTC)},
+               2: {Date(1991, April, 14, 1, 50, 0, 0, loc), Date(1991, April, 13, 17, 50, 0, 0, UTC)},
+               3: {Date(1991, April, 14, 3, 0, 0, 0, loc), Date(1991, April, 13, 18, 0, 0, 0, UTC)},
+
+               // 15 Sep 1991 - Daylight Saving Time Ended
+               // When local daylight time of "Asia/Shanghai" was about to reach
+               // Sunday, 15 September 1991, 02:00:00 clocks were turned backward 1 hour to
+               // Sunday, 15 September 1991, 01:00:00 local standard time instead.
+               // The UTC time was 14 September 1991, 17:00:00
+               4: {Date(1991, September, 14, 16, 50, 0, 0, loc), Date(1991, September, 14, 7, 50, 0, 0, UTC)},
+               5: {Date(1991, September, 14, 17, 0, 0, 0, loc), Date(1991, September, 14, 8, 0, 0, 0, UTC)},
+               6: {Date(1991, September, 15, 0, 50, 0, 0, loc), Date(1991, September, 14, 15, 50, 0, 0, UTC)},
+               7: {Date(1991, September, 15, 2, 00, 0, 0, loc), Date(1991, September, 14, 18, 00, 0, 0, UTC)},
+       }
+
+       for i, tt := range tests {
+               if !tt.give.Equal(tt.want) {
+                       t.Errorf("#%d:: %#v is not equal to %#v", i, tt.give.Format(RFC3339), tt.want.Format(RFC3339))
+               }
+       }
+}