From dcc46388df62fafe81426b8dd888ed786f7db9fa Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 4 Jun 2012 13:09:19 -0400 Subject: [PATCH] time: accept .999 in Parse The recent shuffle in parsing formats exposed probably unintentional behavior in time.Parse, namely that it was mostly ignoring ".99999" in the format, producing the following behavior: fmt.Println(time.Parse("03:04:05.999 MST", "12:00:00.888 PDT")) // error (.888 unexpected) fmt.Println(time.Parse("03:04:05.999", "12:00:00")) // error (input too short) fmt.Println(time.Parse("03:04:05.999 MST", "12:00:00 PDT")) // ok (extra bytes on input make it ok) http://play.golang.org/p/ESJ1UYXzq2 API CHANGE: This CL makes all three examples valid: ".999" can match an empty string or else a fractional second with at most nine digits. Fixes #3701. R=r, r CC=golang-dev https://golang.org/cl/6267045 --- src/pkg/time/format.go | 16 +++++++++++++++- src/pkg/time/time_test.go | 10 ++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/pkg/time/format.go b/src/pkg/time/format.go index b36a58b661..46f4fbc13b 100644 --- a/src/pkg/time/format.go +++ b/src/pkg/time/format.go @@ -852,10 +852,24 @@ func Parse(layout, value string) (Time, error) { // It's a valid format. zoneName = p - case stdFracSecond0, stdFracSecond9: + case stdFracSecond0: ndigit := std >> stdArgShift nsec, rangeErrString, err = parseNanoseconds(value, 1+ndigit) value = value[1+ndigit:] + + case stdFracSecond9: + if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] { + // Fractional second omitted. + break + } + // Take any number of digits, even more than asked for, + // because it is what the stdSecond case would do. + i := 0 + for i < 9 && i+1 < len(value) && '0' <= value[i+1] && value[i+1] <= '9' { + i++ + } + nsec, rangeErrString, err = parseNanoseconds(value, 1+i) + value = value[1+i:] } if rangeErrString != "" { return Time{}, &ParseError{alayout, avalue, stdstr, value, ": " + rangeErrString + " out of range"} diff --git a/src/pkg/time/time_test.go b/src/pkg/time/time_test.go index 68e551e5f7..0204fc29ee 100644 --- a/src/pkg/time/time_test.go +++ b/src/pkg/time/time_test.go @@ -324,6 +324,16 @@ var parseTests = []ParseTest{ // Leading zeros in other places should not be taken as fractional seconds. {"zero1", "2006.01.02.15.04.05.0", "2010.02.04.21.00.57.0", false, false, 1, 1}, {"zero2", "2006.01.02.15.04.05.00", "2010.02.04.21.00.57.01", false, false, 1, 2}, + + // Accept any number of fractional second digits (including none) for .999... + // In Go 1, .999... was completely ignored in the format, meaning the first two + // cases would succeed, but the next four would not. Go 1.1 accepts all six. + {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0}, + {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57 -0800 PST", true, false, 1, 0}, + {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4}, + {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.0123 -0800 PST", true, false, 1, 4}, + {"", "2006-01-02 15:04:05.9999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9}, + {"", "2006-01-02 15:04:05.999999999 -0700 MST", "2010-02-04 21:00:57.012345678 -0800 PST", true, false, 1, 9}, } func TestParse(t *testing.T) { -- 2.48.1