}
if std == 0 {
if len(value) != 0 {
- return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
+ return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + quote(value)}
}
break
}
return 0, nil
}
if s == "" {
- return 0, errors.New("time: invalid duration " + orig)
+ return 0, errors.New("time: invalid duration " + quote(orig))
}
for s != "" {
var (
// The next character must be [0-9.]
if !(s[0] == '.' || '0' <= s[0] && s[0] <= '9') {
- return 0, errors.New("time: invalid duration " + orig)
+ return 0, errors.New("time: invalid duration " + quote(orig))
}
// Consume [0-9]*
pl := len(s)
v, s, err = leadingInt(s)
if err != nil {
- return 0, errors.New("time: invalid duration " + orig)
+ return 0, errors.New("time: invalid duration " + quote(orig))
}
pre := pl != len(s) // whether we consumed anything before a period
}
if !pre && !post {
// no digits (e.g. ".s" or "-.s")
- return 0, errors.New("time: invalid duration " + orig)
+ return 0, errors.New("time: invalid duration " + quote(orig))
}
// Consume unit.
}
}
if i == 0 {
- return 0, errors.New("time: missing unit in duration " + orig)
+ return 0, errors.New("time: missing unit in duration " + quote(orig))
}
u := s[:i]
s = s[i:]
unit, ok := unitMap[u]
if !ok {
- return 0, errors.New("time: unknown unit " + u + " in duration " + orig)
+ return 0, errors.New("time: unknown unit " + quote(u) + " in duration " + quote(orig))
}
if v > (1<<63-1)/unit {
// overflow
- return 0, errors.New("time: invalid duration " + orig)
+ return 0, errors.New("time: invalid duration " + quote(orig))
}
v *= unit
if f > 0 {
v += int64(float64(f) * (float64(unit) / scale))
if v < 0 {
// overflow
- return 0, errors.New("time: invalid duration " + orig)
+ return 0, errors.New("time: invalid duration " + quote(orig))
}
}
d += v
if d < 0 {
// overflow
- return 0, errors.New("time: invalid duration " + orig)
+ return 0, errors.New("time: invalid duration " + quote(orig))
}
}
var parseDurationTests = []struct {
in string
- ok bool
want Duration
}{
// simple
- {"0", true, 0},
- {"5s", true, 5 * Second},
- {"30s", true, 30 * Second},
- {"1478s", true, 1478 * Second},
+ {"0", 0},
+ {"5s", 5 * Second},
+ {"30s", 30 * Second},
+ {"1478s", 1478 * Second},
// sign
- {"-5s", true, -5 * Second},
- {"+5s", true, 5 * Second},
- {"-0", true, 0},
- {"+0", true, 0},
+ {"-5s", -5 * Second},
+ {"+5s", 5 * Second},
+ {"-0", 0},
+ {"+0", 0},
// decimal
- {"5.0s", true, 5 * Second},
- {"5.6s", true, 5*Second + 600*Millisecond},
- {"5.s", true, 5 * Second},
- {".5s", true, 500 * Millisecond},
- {"1.0s", true, 1 * Second},
- {"1.00s", true, 1 * Second},
- {"1.004s", true, 1*Second + 4*Millisecond},
- {"1.0040s", true, 1*Second + 4*Millisecond},
- {"100.00100s", true, 100*Second + 1*Millisecond},
+ {"5.0s", 5 * Second},
+ {"5.6s", 5*Second + 600*Millisecond},
+ {"5.s", 5 * Second},
+ {".5s", 500 * Millisecond},
+ {"1.0s", 1 * Second},
+ {"1.00s", 1 * Second},
+ {"1.004s", 1*Second + 4*Millisecond},
+ {"1.0040s", 1*Second + 4*Millisecond},
+ {"100.00100s", 100*Second + 1*Millisecond},
// different units
- {"10ns", true, 10 * Nanosecond},
- {"11us", true, 11 * Microsecond},
- {"12µs", true, 12 * Microsecond}, // U+00B5
- {"12μs", true, 12 * Microsecond}, // U+03BC
- {"13ms", true, 13 * Millisecond},
- {"14s", true, 14 * Second},
- {"15m", true, 15 * Minute},
- {"16h", true, 16 * Hour},
+ {"10ns", 10 * Nanosecond},
+ {"11us", 11 * Microsecond},
+ {"12µs", 12 * Microsecond}, // U+00B5
+ {"12μs", 12 * Microsecond}, // U+03BC
+ {"13ms", 13 * Millisecond},
+ {"14s", 14 * Second},
+ {"15m", 15 * Minute},
+ {"16h", 16 * Hour},
// composite durations
- {"3h30m", true, 3*Hour + 30*Minute},
- {"10.5s4m", true, 4*Minute + 10*Second + 500*Millisecond},
- {"-2m3.4s", true, -(2*Minute + 3*Second + 400*Millisecond)},
- {"1h2m3s4ms5us6ns", true, 1*Hour + 2*Minute + 3*Second + 4*Millisecond + 5*Microsecond + 6*Nanosecond},
- {"39h9m14.425s", true, 39*Hour + 9*Minute + 14*Second + 425*Millisecond},
+ {"3h30m", 3*Hour + 30*Minute},
+ {"10.5s4m", 4*Minute + 10*Second + 500*Millisecond},
+ {"-2m3.4s", -(2*Minute + 3*Second + 400*Millisecond)},
+ {"1h2m3s4ms5us6ns", 1*Hour + 2*Minute + 3*Second + 4*Millisecond + 5*Microsecond + 6*Nanosecond},
+ {"39h9m14.425s", 39*Hour + 9*Minute + 14*Second + 425*Millisecond},
// large value
- {"52763797000ns", true, 52763797000 * Nanosecond},
+ {"52763797000ns", 52763797000 * Nanosecond},
// more than 9 digits after decimal point, see https://golang.org/issue/6617
- {"0.3333333333333333333h", true, 20 * Minute},
+ {"0.3333333333333333333h", 20 * Minute},
// 9007199254740993 = 1<<53+1 cannot be stored precisely in a float64
- {"9007199254740993ns", true, (1<<53 + 1) * Nanosecond},
+ {"9007199254740993ns", (1<<53 + 1) * Nanosecond},
// largest duration that can be represented by int64 in nanoseconds
- {"9223372036854775807ns", true, (1<<63 - 1) * Nanosecond},
- {"9223372036854775.807us", true, (1<<63 - 1) * Nanosecond},
- {"9223372036s854ms775us807ns", true, (1<<63 - 1) * Nanosecond},
+ {"9223372036854775807ns", (1<<63 - 1) * Nanosecond},
+ {"9223372036854775.807us", (1<<63 - 1) * Nanosecond},
+ {"9223372036s854ms775us807ns", (1<<63 - 1) * Nanosecond},
// large negative value
- {"-9223372036854775807ns", true, -1<<63 + 1*Nanosecond},
+ {"-9223372036854775807ns", -1<<63 + 1*Nanosecond},
// huge string; issue 15011.
- {"0.100000000000000000000h", true, 6 * Minute},
+ {"0.100000000000000000000h", 6 * Minute},
// This value tests the first overflow check in leadingFraction.
- {"0.830103483285477580700h", true, 49*Minute + 48*Second + 372539827*Nanosecond},
-
- // errors
- {"", false, 0},
- {"3", false, 0},
- {"-", false, 0},
- {"s", false, 0},
- {".", false, 0},
- {"-.", false, 0},
- {".s", false, 0},
- {"+.s", false, 0},
- {"3000000h", false, 0}, // overflow
- {"9223372036854775808ns", false, 0}, // overflow
- {"9223372036854775.808us", false, 0}, // overflow
- {"9223372036854ms775us808ns", false, 0}, // overflow
- // largest negative value of type int64 in nanoseconds should fail
- // see https://go-review.googlesource.com/#/c/2461/
- {"-9223372036854775808ns", false, 0},
+ {"0.830103483285477580700h", 49*Minute + 48*Second + 372539827*Nanosecond},
}
func TestParseDuration(t *testing.T) {
for _, tc := range parseDurationTests {
d, err := ParseDuration(tc.in)
- if tc.ok && (err != nil || d != tc.want) {
+ if err != nil || d != tc.want {
t.Errorf("ParseDuration(%q) = %v, %v, want %v, nil", tc.in, d, err, tc.want)
- } else if !tc.ok && err == nil {
+ }
+ }
+}
+
+var parseDurationErrorTests = []struct {
+ in string
+ expect string
+}{
+ // invalid
+ {"", `""`},
+ {"3", `"3"`},
+ {"-", `"-"`},
+ {"s", `"s"`},
+ {".", `"."`},
+ {"-.", `"-."`},
+ {".s", `".s"`},
+ {"+.s", `"+.s"`},
+ {"1d", `"1d"`},
+ // overflow
+ {"9223372036854775810ns", `"9223372036854775810ns"`},
+ {"9223372036854775808ns", `"9223372036854775808ns"`},
+ // largest negative value of type int64 in nanoseconds should fail
+ // see https://go-review.googlesource.com/#/c/2461/
+ {"-9223372036854775808ns", `"-9223372036854775808ns"`},
+ {"9223372036854776us", `"9223372036854776us"`},
+ {"3000000h", `"3000000h"`},
+ {"9223372036854775.808us", `"9223372036854775.808us"`},
+ {"9223372036854ms775us808ns", `"9223372036854ms775us808ns"`},
+}
+
+func TestParseDurationErrors(t *testing.T) {
+ for _, tc := range parseDurationErrorTests {
+ _, err := ParseDuration(tc.in)
+ if err == nil {
t.Errorf("ParseDuration(%q) = _, nil, want _, non-nil", tc.in)
+ } else if !strings.Contains(err.Error(), tc.expect) {
+ t.Errorf("ParseDuration(%q) = _, %q, error does not contain %q", tc.in, err, tc.expect)
}
}
}