mirror of
https://github.com/golang/go
synced 2024-11-21 23:24:41 -07:00
time: fix time zones yet again.
This time we're going for 5! http://goo.gl/3ETYH7 Fixes #3790 Yeah, right. R=golang-dev, adg CC=golang-dev https://golang.org/cl/13002044
This commit is contained in:
parent
ea6cfc57b3
commit
4c855f3830
@ -17,3 +17,5 @@ func ForceUSPacificForTesting() {
|
||||
ResetLocalOnceForTest()
|
||||
localOnce.Do(initTestingZone)
|
||||
}
|
||||
|
||||
var ParseTimeZone = parseTimeZone
|
||||
|
@ -1027,8 +1027,11 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
|
||||
// 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.
|
||||
// there. We look at the beginning of the string for a run of upper-case letters.
|
||||
// If there are more than 5, it's an error.
|
||||
// If there are 4 or 5 and the last is a T, it's a time zone.
|
||||
// If there are 3, it's a time zone.
|
||||
// Otherwise, other than special cases, it's not a time zone.
|
||||
// GMT is special because it can have an hour offset.
|
||||
func parseTimeZone(value string) (length int, ok bool) {
|
||||
if len(value) < 3 {
|
||||
@ -1043,19 +1046,31 @@ func parseTimeZone(value string) (length int, ok bool) {
|
||||
length = parseGMT(value)
|
||||
return length, true
|
||||
}
|
||||
// There must be three upper-case letters.
|
||||
for i := 0; i < 3; i++ {
|
||||
c := value[i]
|
||||
if c < 'A' || 'Z' < c {
|
||||
return 0, false
|
||||
// How many upper-case letters are there? Need at least three, at most five.
|
||||
var nUpper int
|
||||
for nUpper = 0; nUpper < 6; nUpper++ {
|
||||
if nUpper >= len(value) {
|
||||
break
|
||||
}
|
||||
if c := value[nUpper]; c < 'A' || 'Z' < c {
|
||||
break
|
||||
}
|
||||
}
|
||||
// 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
|
||||
switch nUpper {
|
||||
case 0, 1, 2, 6:
|
||||
return 0, false
|
||||
case 5: // Must end in T to match.
|
||||
if value[4] == 'T' {
|
||||
return 5, true
|
||||
}
|
||||
case 4: // Must end in T to match.
|
||||
if value[3] == 'T' {
|
||||
return 4, true
|
||||
}
|
||||
case 3:
|
||||
return 3, true
|
||||
}
|
||||
return 3, true
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// parseGMT parses a GMT time zone. The input string is known to start "GMT".
|
||||
|
@ -666,6 +666,38 @@ func TestFormatAndParse(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
type ParseTimeZoneTest struct {
|
||||
value string
|
||||
length int
|
||||
ok bool
|
||||
}
|
||||
|
||||
var parseTimeZoneTests = []ParseTimeZoneTest{
|
||||
{"gmt hi there", 0, false},
|
||||
{"GMT hi there", 3, true},
|
||||
{"GMT+12 hi there", 6, true},
|
||||
{"GMT+00 hi there", 3, true}, // 0 or 00 is not a legal offset.
|
||||
{"GMT-5 hi there", 5, true},
|
||||
{"GMT-51 hi there", 3, true},
|
||||
{"ChST hi there", 4, true},
|
||||
{"MSDx", 3, true},
|
||||
{"MSDY", 0, false}, // four letters must end in T.
|
||||
{"ESAST hi", 5, true},
|
||||
{"ESASTT hi", 0, false}, // run of upper-case letters too long.
|
||||
{"ESATY hi", 0, false}, // five letters must end in T.
|
||||
}
|
||||
|
||||
func TestParseTimeZone(t *testing.T) {
|
||||
for _, test := range parseTimeZoneTests {
|
||||
length, ok := ParseTimeZone(test.value)
|
||||
if ok != test.ok {
|
||||
t.Errorf("expected %t for %q got %t", test.ok, test.value, ok)
|
||||
} else if length != test.length {
|
||||
t.Errorf("expected %d for %q got %d", test.length, test.value, length)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ParseErrorTest struct {
|
||||
format string
|
||||
value string
|
||||
|
Loading…
Reference in New Issue
Block a user