Skip to content

Commit

Permalink
Fix negative duration parsing
Browse files Browse the repository at this point in the history
Only the one the negative one that could be parsed with strconv.ParseDuration were working.
Now all negative durations are working.
  • Loading branch information
ccoVeille committed Jan 21, 2025
1 parent 75847d1 commit 589326a
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
13 changes: 11 additions & 2 deletions duration.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ var (
"w": 7 * 24 * time.Hour,
}

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

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

factor, err := strconv.Atoi(match[2]) // converts string to int
// remove possible leading - and spaces
value, negative := strings.CutPrefix(match[2], "-")

// if the string is a valid duration, parse it
factor, err := strconv.Atoi(strings.TrimSpace(value)) // converts string to int
if err != nil {
return 0, err
}

if negative {
factor = -factor
}

unit := strings.ToLower(strings.TrimSpace(match[3]))

for _, variants := range timeUnits {
Expand Down
14 changes: 10 additions & 4 deletions duration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ func TestDurationScanner_Nil(t *testing.T) {

func TestDurationParser(t *testing.T) {
testcases := map[string]time.Duration{

// parse the short forms without spaces
"1ns": 1 * time.Nanosecond,
"1us": 1 * time.Microsecond,
Expand Down Expand Up @@ -182,10 +181,18 @@ func TestDurationParser(t *testing.T) {
}

for str, dur := range testcases {
testDurationParser(t, str, dur)
testDurationSQLScanner(t, dur)
t.Run(str, func(t *testing.T) {
testDurationParser(t, str, dur)

// negative duration
testDurationParser(t, "-"+str, -dur)
testDurationParser(t, "- "+str, -dur)

testDurationSQLScanner(t, dur)
})
}
}

func TestIsDuration_Caveats(t *testing.T) {
// This works too
e := IsDuration("45 weeks")
Expand All @@ -206,7 +213,6 @@ func TestIsDuration_Caveats(t *testing.T) {
// This does not work
e = IsDuration("12 phours")
assert.False(t, e)

}

func TestDeepCopyDuration(t *testing.T) {
Expand Down

0 comments on commit 589326a

Please sign in to comment.