]> Cypherpunks repositories - gostls13.git/commitdiff
time: truncate fractional seconds longer than 9 digits
authorAlexander Yastrebov <yastrebov.alex@gmail.com>
Sun, 3 Oct 2021 15:45:38 +0000 (15:45 +0000)
committerIan Lance Taylor <iant@golang.org>
Wed, 6 Oct 2021 19:45:35 +0000 (19:45 +0000)
Fixes #48685

Change-Id: Id246708878c2902b407ab759537f6b545a1f459f
GitHub-Last-Rev: 4d985192c5a66ae8891539f166ef88b53cd1cbea
GitHub-Pull-Request: golang/go#48750
Reviewed-on: https://go-review.googlesource.com/c/go/+/353713
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
Trust: Emmanuel Odeke <emmanuel@orijtech.com>

src/time/format.go
src/time/format_test.go

index 7373892b9772f878264a6e5f4e81a186cef93037..464effdb438885a20f3d09378c8006919623b4a3 100644 (file)
@@ -1420,16 +1420,19 @@ func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string,
                err = errBad
                return
        }
+       if nbytes > 10 {
+               value = value[:10]
+               nbytes = 10
+       }
        if ns, err = atoi(value[1:nbytes]); err != nil {
                return
        }
-       if ns < 0 || 1e9 <= ns {
+       if ns < 0 {
                rangeErrString = "fractional second"
                return
        }
        // We need nanoseconds, which means scaling by the number
-       // of missing digits in the format, maximum length 10. If it's
-       // longer than 10, we won't scale.
+       // of missing digits in the format, maximum length 10.
        scaleDigits := 10 - nbytes
        for i := 0; i < scaleDigits; i++ {
                ns *= 10
index 93cbcf940139292ca02a5f721d381059c0f20d76..db95536390040ba692271eef48f0bf5078c57672 100644 (file)
@@ -852,3 +852,44 @@ func TestFormatFractionalSecondSeparators(t *testing.T) {
                }
        }
 }
+
+// Issue 48685
+func TestParseFractionalSecondsLongerThanNineDigits(t *testing.T) {
+       tests := []struct {
+               s    string
+               want int
+       }{
+               // 9 digits
+               {"2021-09-29T16:04:33.000000000Z", 0},
+               {"2021-09-29T16:04:33.000000001Z", 1},
+               {"2021-09-29T16:04:33.100000000Z", 100_000_000},
+               {"2021-09-29T16:04:33.100000001Z", 100_000_001},
+               {"2021-09-29T16:04:33.999999999Z", 999_999_999},
+               {"2021-09-29T16:04:33.012345678Z", 12_345_678},
+               // 10 digits, truncates
+               {"2021-09-29T16:04:33.0000000000Z", 0},
+               {"2021-09-29T16:04:33.0000000001Z", 0},
+               {"2021-09-29T16:04:33.1000000000Z", 100_000_000},
+               {"2021-09-29T16:04:33.1000000009Z", 100_000_000},
+               {"2021-09-29T16:04:33.9999999999Z", 999_999_999},
+               {"2021-09-29T16:04:33.0123456789Z", 12_345_678},
+               // 11 digits, truncates
+               {"2021-09-29T16:04:33.10000000000Z", 100_000_000},
+               {"2021-09-29T16:04:33.00123456789Z", 1_234_567},
+               // 12 digits, truncates
+               {"2021-09-29T16:04:33.000123456789Z", 123_456},
+               // 15 digits, truncates
+               {"2021-09-29T16:04:33.9999999999999999Z", 999_999_999},
+       }
+
+       for _, tt := range tests {
+               tm, err := Parse(RFC3339, tt.s)
+               if err != nil {
+                       t.Errorf("Unexpected error: %v", err)
+                       continue
+               }
+               if got := tm.Nanosecond(); got != tt.want {
+                       t.Errorf("Parse(%q) = got %d, want %d", tt.s, got, tt.want)
+               }
+       }
+}