Skip to content

Commit

Permalink
time: fix misleading error with the leading zero format
Browse files Browse the repository at this point in the history
When the leading zero format is used, we currently don't handle the
month and year properly.

For the month, we were reporting an out of range error when getnum
returns zero of its own, as it also returns the month 0. That's
confusing, so only check the range when getnum returns a nil error.

For the year, we don't restore the value when parsing error occurs. For
example, with the incorrect input "111-01", "01" will be used to report
an error. So restore the value when an error occurs fix the problem.

Fixes golang#29918
Fixes golang#29916

Change-Id: I3145f8c46813a0457766b7c302482e6b56f94ed6
Reviewed-on: https://go-review.googlesource.com/c/go/+/160338
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
  • Loading branch information
cuonglm authored and ianlancetaylor committed Apr 26, 2019
1 parent bc48cc7 commit 8feeada
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/time/format.go
Expand Up @@ -865,9 +865,12 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
err = errBad
break
}
hold := value
p, value = value[0:2], value[2:]
year, err = atoi(p)
if year >= 69 { // Unix time starts Dec 31 1969 in some time zones
if err != nil {
value = hold
} else if year >= 69 { // Unix time starts Dec 31 1969 in some time zones
year += 1900
} else {
year += 2000
Expand All @@ -887,7 +890,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
month++
case stdNumMonth, stdZeroMonth:
month, value, err = getnum(value, std == stdZeroMonth)
if month <= 0 || 12 < month {
if err == nil && (month <= 0 || 12 < month) {
rangeErrString = "month"
}
case stdWeekDay:
Expand Down
46 changes: 46 additions & 0 deletions src/time/format_test.go
Expand Up @@ -710,3 +710,49 @@ func TestUnderscoreTwoThousand(t *testing.T) {
t.Errorf("Incorrect minute, got %d", m)
}
}

// Issue 29918, 29916
func TestStd0xParseError(t *testing.T) {
tests := []struct {
format, value, valueElemPrefix string
}{
{"01 MST", "0 MST", "0"},
{"01 MST", "1 MST", "1"},
{RFC850, "Thursday, 04-Feb-1 21:00:57 PST", "1"},
}
for _, tt := range tests {
_, err := Parse(tt.format, tt.value)
if err == nil {
t.Errorf("Parse(%q, %q) did not fail as expected", tt.format, tt.value)
} else if perr, ok := err.(*ParseError); !ok {
t.Errorf("Parse(%q, %q) returned error type %T, expected ParseError", tt.format, tt.value, perr)
} else if !strings.Contains(perr.Error(), "cannot parse") || !strings.HasPrefix(perr.ValueElem, tt.valueElemPrefix) {
t.Errorf("Parse(%q, %q) returned wrong parsing error message: %v", tt.format, tt.value, perr)
}
}
}

var monthOutOfRangeTests = []struct {
value string
ok bool
}{
{"00-01", false},
{"13-01", false},
{"01-01", true},
}

func TestParseMonthOutOfRange(t *testing.T) {
for _, test := range monthOutOfRangeTests {
_, err := Parse("01-02", test.value)
switch {
case !test.ok && err != nil:
if !strings.Contains(err.Error(), "month out of range") {
t.Errorf("%q: expected 'month' error, got %v", test.value, err)
}
case test.ok && err != nil:
t.Errorf("%q: unexpected error: %v", test.value, err)
case !test.ok && err == nil:
t.Errorf("%q: expected 'month' error, got none", test.value)
}
}
}

0 comments on commit 8feeada

Please sign in to comment.