From aa05238cf2550070fa2fad6e9756d16f87843d9f Mon Sep 17 00:00:00 2001 From: Mark Rosemaker <48681726+MarkRosemaker@users.noreply.github.com> Date: Sat, 16 Jul 2022 19:09:18 +0200 Subject: [PATCH 1/2] time: adjust time zone seconds offset in parse Fixes #53919 --- src/time/format.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/time/format.go b/src/time/format.go index 5f696189ff114f..d1b4be47fe106f 100644 --- a/src/time/format.go +++ b/src/time/format.go @@ -973,6 +973,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) rangeErrString := "" // set if a value is out of range amSet := false // do we need to subtract 12 from the hour for midnight? pmSet := false // do we need to add 12 to the hour? + secsSet := false // are seconds explictly set? // Time being constructed. var ( @@ -1159,12 +1160,14 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) break } sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], value[7:9], value[9:] + secsSet = true } else if std == stdISO8601SecondsTZ || std == stdNumSecondsTz { if len(value) < 7 { err = errBad break } sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], value[5:7], value[7:] + secsSet = true } else { if len(value) < 5 { err = errBad @@ -1297,6 +1300,15 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) // 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.unixSec()) + + if !secsSet { + if diff := offset - zoneOffset; -60 < diff && diff < 60 { + // The difference of local offset and the zone offset is mere seconds and seconds weren't explictly set. + t.addSec(-int64(diff)) + zoneOffset += diff + } + } + if offset == zoneOffset && (zoneName == "" || name == zoneName) { t.setLoc(local) return t, nil From 8874c8ceb889d4563426b1be885e635211ee06b4 Mon Sep 17 00:00:00 2001 From: Mark Rosemaker <48681726+MarkRosemaker@users.noreply.github.com> Date: Sat, 16 Jul 2022 19:10:36 +0200 Subject: [PATCH 2/2] time: test seconds offset adjustment --- src/time/format_test.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/time/format_test.go b/src/time/format_test.go index ab72fae3231819..0268df3781639b 100644 --- a/src/time/format_test.go +++ b/src/time/format_test.go @@ -893,3 +893,35 @@ func TestParseFractionalSecondsLongerThanNineDigits(t *testing.T) { } } } + +// Issue 53919 +func TestParseInLocationSecondsAdjusted(t *testing.T) { + t.Parallel() + + zName := "Asia/Shanghai" + + z, err := LoadLocation(zName) + if err != nil { + t.Errorf("Unexpected error: %v", err) + return + } + + ts := Date(1900, 1, 1, 0, 0, 0, 0, z) + s := ts.Format(RFC3339Nano) + + ts, err = ParseInLocation(RFC3339, s, z) + if err != nil { + t.Errorf("Unexpected error: %v", err) + return + } + + if got := ts.Location().String(); zName != got { + t.Errorf("ParseInLocation returns wrong location; got %q, want %q", got, zName) + + ts = ts.In(z) + } + + if got := ts.Format(RFC3339Nano); s != got { + t.Errorf("seconds were not adjusted; got %q, want %q", got, s) + } +}