diff options
author | Meng Zhuo <mzh@golangcn.org> | 2021-09-26 14:56:55 +0800 |
---|---|---|
committer | Meng Zhuo <mzh@golangcn.org> | 2021-10-08 14:08:12 +0000 |
commit | 5b9206f64ef4d8ea3201627cf9ba5c2b86e65022 (patch) | |
tree | a9522cf54d0db6a6eb50252c4cf33285bfa2d3ae /src/time/format.go | |
parent | e74db46519a7cbed16a7f14932da2ef93d647ece (diff) | |
download | go-5b9206f64ef4d8ea3201627cf9ba5c2b86e65022.tar.gz go-5b9206f64ef4d8ea3201627cf9ba5c2b86e65022.zip |
time: allow minimum int64 in ParseDuration
ParseDuration should handle minimum int64 (-1<<63) nanosecond
since type Duration is alias of int64
name old time/op new time/op delta
ParseDuration 91.4ns ± 0% 86.4ns ± 1% -5.49% (p=0.000 n=9+8)
Fixes: #48629
Change-Id: I81b7035b25cefb4c1e5b7801c20f2d335e29358a
Reviewed-on: https://go-review.googlesource.com/c/go/+/352269
Trust: Meng Zhuo <mzh@golangcn.org>
Run-TryBot: Meng Zhuo <mzh@golangcn.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/time/format.go')
-rw-r--r-- | src/time/format.go | 56 |
1 files changed, 27 insertions, 29 deletions
diff --git a/src/time/format.go b/src/time/format.go index 464effdb43..5fb9cdc969 100644 --- a/src/time/format.go +++ b/src/time/format.go @@ -1402,10 +1402,7 @@ func parseSignedOffset(value string) int { if err != nil || value[1:] == rem { return 0 } - if sign == '-' { - x = -x - } - if x < -23 || 23 < x { + if x > 23 { return 0 } return len(value) - len(rem) @@ -1443,19 +1440,19 @@ func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, var errLeadingInt = errors.New("time: bad [0-9]*") // never printed // leadingInt consumes the leading [0-9]* from s. -func leadingInt(s string) (x int64, rem string, err error) { +func leadingInt(s string) (x uint64, rem string, err error) { i := 0 for ; i < len(s); i++ { c := s[i] if c < '0' || c > '9' { break } - if x > (1<<63-1)/10 { + if x > 1<<63/10 { // overflow return 0, "", errLeadingInt } - x = x*10 + int64(c) - '0' - if x < 0 { + x = x*10 + uint64(c) - '0' + if x > 1<<63 { // overflow return 0, "", errLeadingInt } @@ -1466,7 +1463,7 @@ func leadingInt(s string) (x int64, rem string, err error) { // leadingFraction consumes the leading [0-9]* from s. // It is used only for fractions, so does not return an error on overflow, // it just stops accumulating precision. -func leadingFraction(s string) (x int64, scale float64, rem string) { +func leadingFraction(s string) (x uint64, scale float64, rem string) { i := 0 scale = 1 overflow := false @@ -1483,8 +1480,8 @@ func leadingFraction(s string) (x int64, scale float64, rem string) { overflow = true continue } - y := x*10 + int64(c) - '0' - if y < 0 { + y := x*10 + uint64(c) - '0' + if y > 1<<63 { overflow = true continue } @@ -1494,15 +1491,15 @@ func leadingFraction(s string) (x int64, scale float64, rem string) { return x, scale, s[i:] } -var unitMap = map[string]int64{ - "ns": int64(Nanosecond), - "us": int64(Microsecond), - "µs": int64(Microsecond), // U+00B5 = micro symbol - "μs": int64(Microsecond), // U+03BC = Greek letter mu - "ms": int64(Millisecond), - "s": int64(Second), - "m": int64(Minute), - "h": int64(Hour), +var unitMap = map[string]uint64{ + "ns": uint64(Nanosecond), + "us": uint64(Microsecond), + "µs": uint64(Microsecond), // U+00B5 = micro symbol + "μs": uint64(Microsecond), // U+03BC = Greek letter mu + "ms": uint64(Millisecond), + "s": uint64(Second), + "m": uint64(Minute), + "h": uint64(Hour), } // ParseDuration parses a duration string. @@ -1513,7 +1510,7 @@ var unitMap = map[string]int64{ func ParseDuration(s string) (Duration, error) { // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+ orig := s - var d int64 + var d uint64 neg := false // Consume [-+]? @@ -1533,7 +1530,7 @@ func ParseDuration(s string) (Duration, error) { } for s != "" { var ( - v, f int64 // integers before, after decimal point + v, f uint64 // integers before, after decimal point scale float64 = 1 // value = v + f/scale ) @@ -1581,7 +1578,7 @@ func ParseDuration(s string) (Duration, error) { if !ok { return 0, errors.New("time: unknown unit " + quote(u) + " in duration " + quote(orig)) } - if v > (1<<63-1)/unit { + if v > 1<<63/unit { // overflow return 0, errors.New("time: invalid duration " + quote(orig)) } @@ -1589,21 +1586,22 @@ func ParseDuration(s string) (Duration, error) { if f > 0 { // float64 is needed to be nanosecond accurate for fractions of hours. // v >= 0 && (f*unit/scale) <= 3.6e+12 (ns/h, h is the largest unit) - v += int64(float64(f) * (float64(unit) / scale)) - if v < 0 { + v += uint64(float64(f) * (float64(unit) / scale)) + if v > 1<<63 { // overflow return 0, errors.New("time: invalid duration " + quote(orig)) } } d += v - if d < 0 { - // overflow + if d > 1<<63 { return 0, errors.New("time: invalid duration " + quote(orig)) } } - if neg { - d = -d + return -Duration(d), nil + } + if d > 1<<63-1 { + return 0, errors.New("time: invalid duration " + quote(orig)) } return Duration(d), nil } |