From dafb786c8df9a6ec754d25b0a913c0dd261fed47 Mon Sep 17 00:00:00 2001 From: Jefftree Date: Wed, 13 Aug 2025 21:02:38 +0000 Subject: [PATCH] Fix negative duration parsing --- pkg/validation/strfmt/duration.go | 12 ++++++++++-- pkg/validation/strfmt/duration_test.go | 8 +++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/pkg/validation/strfmt/duration.go b/pkg/validation/strfmt/duration.go index 8fbeb635f..b655d16eb 100644 --- a/pkg/validation/strfmt/duration.go +++ b/pkg/validation/strfmt/duration.go @@ -52,7 +52,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 @@ -94,10 +94,18 @@ 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 { diff --git a/pkg/validation/strfmt/duration_test.go b/pkg/validation/strfmt/duration_test.go index eeb4ff35d..9f1d2b823 100644 --- a/pkg/validation/strfmt/duration_test.go +++ b/pkg/validation/strfmt/duration_test.go @@ -141,7 +141,13 @@ func TestDurationParser(t *testing.T) { } for str, dur := range testcases { - testDurationParser(t, str, dur) + t.Run(str, func(t *testing.T) { + testDurationParser(t, str, dur) + + // negative duration + testDurationParser(t, "-"+str, -dur) + testDurationParser(t, "- "+str, -dur) + }) } } func TestIsDuration_Caveats(t *testing.T) {