From a454d2fd2e6a60648728ca6c959a7c0b24119fec Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Thu, 15 Aug 2013 16:42:54 +1000 Subject: [PATCH] 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 --- src/pkg/time/format.go | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/pkg/time/format.go b/src/pkg/time/format.go index ae13811d412..3abe1c210da 100644 --- a/src/pkg/time/format.go +++ b/src/pkg/time/format.go @@ -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".