Commit 9f2c611f authored by Michael Kasch's avatar Michael Kasch Committed by Brad Fitzpatrick

time: add support for parsing timezones denoted by sign and offset

IANA Zoneinfo does not provide names for all timezones. Some are denoted
by a sign and an offset only. E.g: Europe/Turkey is currently +03 or
America/La_Paz which is -04 (https://data.iana.org/time-zones/releases/tzdata2018c.tar.gz)

Fixes #24071

Change-Id: I9c230a719945e1263c5b52bab82084d22861be3e
Reviewed-on: https://go-review.googlesource.com/98157Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 3d69ef37
...@@ -1117,6 +1117,11 @@ func parseTimeZone(value string) (length int, ok bool) { ...@@ -1117,6 +1117,11 @@ func parseTimeZone(value string) (length int, ok bool) {
length = parseGMT(value) length = parseGMT(value)
return length, true return length, true
} }
// Special Case 3: Some time zones are not named, but have +/-00 format
if value[0] == '+' || value[0] == '-' {
length = parseSignedOffset(value)
return length, true
}
// How many upper-case letters are there? Need at least three, at most five. // How many upper-case letters are there? Need at least three, at most five.
var nUpper int var nUpper int
for nUpper = 0; nUpper < 6; nUpper++ { for nUpper = 0; nUpper < 6; nUpper++ {
...@@ -1153,21 +1158,29 @@ func parseGMT(value string) int { ...@@ -1153,21 +1158,29 @@ func parseGMT(value string) int {
if len(value) == 0 { if len(value) == 0 {
return 3 return 3
} }
return 3 + parseSignedOffset(value)
}
// parseSignedOffset parses a signed timezone offset (e.g. "+03" or "-04").
// The function checks for a signed number in the range -14 through +12 excluding zero.
// Returns length of the found offset string or 0 otherwise
func parseSignedOffset(value string) int {
sign := value[0] sign := value[0]
if sign != '-' && sign != '+' { if sign != '-' && sign != '+' {
return 3 return 0
} }
x, rem, err := leadingInt(value[1:]) x, rem, err := leadingInt(value[1:])
if err != nil { if err != nil {
return 3 return 0
} }
if sign == '-' { if sign == '-' {
x = -x x = -x
} }
if x == 0 || x < -14 || 12 < x { if x == 0 || x < -14 || 12 < x {
return 3 return 0
} }
return 3 + len(value) - len(rem) return len(value) - len(rem)
} }
func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) { func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
......
...@@ -427,6 +427,8 @@ var parseTimeZoneTests = []ParseTimeZoneTest{ ...@@ -427,6 +427,8 @@ var parseTimeZoneTests = []ParseTimeZoneTest{
{"ESASTT hi", 0, false}, // run of upper-case letters too long. {"ESASTT hi", 0, false}, // run of upper-case letters too long.
{"ESATY hi", 0, false}, // five letters must end in T. {"ESATY hi", 0, false}, // five letters must end in T.
{"WITA hi", 4, true}, // Issue #18251 {"WITA hi", 4, true}, // Issue #18251
{"+03 hi", 3, true}, // Issue #24071
{"-04 hi", 3, true}, // Issue #24071
} }
func TestParseTimeZone(t *testing.T) { func TestParseTimeZone(t *testing.T) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment