Skip to content

Commit c8413cf

Browse files
ccoVeillefredbi
authored andcommitted
Fix negative duration parsing
Only the one the negative one that could be parsed with strconv.ParseDuration were working. Now all negative durations are working. Signed-off-by: ccoVeille <[email protected]>
1 parent 9ad8f15 commit c8413cf

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

duration.go

+11-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ var (
6060
"w": hoursInDay * daysInWeek * time.Hour,
6161
}
6262

63-
durationMatcher = regexp.MustCompile(`((\d+)\s*([A-Za-zµ]+))`)
63+
durationMatcher = regexp.MustCompile(`(((?:-\s?)?\d+)\s*([A-Za-zµ]+))`)
6464
)
6565

6666
// IsDuration returns true if the provided string is a valid duration
@@ -102,10 +102,19 @@ func ParseDuration(cand string) (time.Duration, error) {
102102
ok := false
103103
for _, match := range durationMatcher.FindAllStringSubmatch(cand, -1) {
104104

105-
factor, err := strconv.Atoi(match[2]) // converts string to int
105+
// remove possible leading - and spaces
106+
value, negative := strings.CutPrefix(match[2], "-")
107+
108+
// if the string is a valid duration, parse it
109+
factor, err := strconv.Atoi(strings.TrimSpace(value)) // converts string to int
106110
if err != nil {
107111
return 0, err
108112
}
113+
114+
if negative {
115+
factor = -factor
116+
}
117+
109118
unit := strings.ToLower(strings.TrimSpace(match[3]))
110119

111120
for _, variants := range timeUnits {

duration_test.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@ func TestDurationScanner_Nil(t *testing.T) {
123123

124124
func TestDurationParser(t *testing.T) {
125125
testcases := map[string]time.Duration{
126-
127126
// parse the short forms without spaces
128127
"1ns": 1 * time.Nanosecond,
129128
"1us": 1 * time.Microsecond,
@@ -182,10 +181,18 @@ func TestDurationParser(t *testing.T) {
182181
}
183182

184183
for str, dur := range testcases {
185-
testDurationParser(t, str, dur)
186-
testDurationSQLScanner(t, dur)
184+
t.Run(str, func(t *testing.T) {
185+
testDurationParser(t, str, dur)
186+
187+
// negative duration
188+
testDurationParser(t, "-"+str, -dur)
189+
testDurationParser(t, "- "+str, -dur)
190+
191+
testDurationSQLScanner(t, dur)
192+
})
187193
}
188194
}
195+
189196
func TestIsDuration_Caveats(t *testing.T) {
190197
// This works too
191198
e := IsDuration("45 weeks")
@@ -206,7 +213,6 @@ func TestIsDuration_Caveats(t *testing.T) {
206213
// This does not work
207214
e = IsDuration("12 phours")
208215
assert.False(t, e)
209-
210216
}
211217

212218
func TestDeepCopyDuration(t *testing.T) {

0 commit comments

Comments
 (0)