Commit a454d2fd authored by Rob Pike's avatar Rob Pike

time: expand acceptance of time zones when parsing

I tried to make it absolutely correct but there are too many
conflicting definitions for the official list of time zones.
Since when we're parsing we know when to expect
a time zone and we know what they look like if not exactly
what the definitive set is, we compromise. We accept any
three-character sequence of upper case letters, possibly
followed by a capital T (all four-letter zones end in T).

There is one crazy special case (ChST) and the possibility
of a signed hour offset for GMT.

Fixes #3790
I hope forever, but I doubt that very much.

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/12969043
parent ec837ad7
......@@ -1023,30 +1023,39 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil
}
// parseTimeZone parses a time zone string and returns its length.
// parseTimeZone parses a time zone string and returns its length. Time zones
// are human-generated and unpredictable. We can't do precise error checking.
// On the other hand, for a correct parse there must be a time zone at the
// beginning of the string, so it's almost always true that there's one
// there. We check: 3 or 4 upper case letters (with one exception). If 4, the
// last letter must be a T.
// GMT is special because it can have an hour offset.
func parseTimeZone(value string) (length int, ok bool) {
if len(value) < 3 {
return 0, false
}
// GMT may have an offset.
if len(value) >= 3 && value[:3] == "GMT" {
// Special case 1: This is the only zone with a lower-case letter.
if len(value) >= 4 && value[:4] == "ChST" {
return 4, true
}
// Special case 2: GMT may have an hour offset; treat it specially.
if value[:3] == "GMT" {
length = parseGMT(value)
return length, true
}
if len(value) >= 3 && value[2] == 'T' {
length = 3
} else if len(value) >= 4 && value[3] == 'T' {
length = 4
} else {
return 0, false
}
for i := 0; i < length; i++ {
if value[i] < 'A' || 'Z' < value[i] {
// There must be three upper-case letters.
for i := 0; i < 3; i++ {
c := value[i]
if c < 'A' || 'Z' < c {
return 0, false
}
}
return length, true
// There may be a fourth upper case letter. If so, in a time zone it's always a 'T'.
// (The last letter is often not a 'T' in three-letter zones: MSK, MSD, HAE, etc.)
if len(value) >= 4 && value[3] == 'T' {
return 4, true
}
return 3, true
}
// parseGMT parses a GMT time zone. The input string is known to start "GMT".
......
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