From 4e86df1721d65ecf211a27282916f7cccabd4007 Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Sat, 27 May 2023 23:55:08 +0300 Subject: [PATCH] util/time: fix duration parsing Signed-off-by: Vasiliy Tolstov --- util/time/duration.go | 64 +++++++++++++++++++++----------------- util/time/duration_test.go | 7 ++--- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/util/time/duration.go b/util/time/duration.go index ae2b716f..456c6bad 100644 --- a/util/time/duration.go +++ b/util/time/duration.go @@ -2,7 +2,9 @@ package time import ( "encoding/json" + "errors" "fmt" + "strconv" "time" ) @@ -13,39 +15,43 @@ func ParseDuration(s string) (time.Duration, error) { return 0, fmt.Errorf(`time: invalid duration "` + s + `"`) } - //var sb strings.Builder - /* - for i, r := range s { - switch r { - case 'd': - n, err := strconv.Atoi(s[idx:i]) - if err != nil { - return 0, errors.New("time: invalid duration " + s) - } - s[idx:i] = fmt.Sprintf("%d", n*24) - default: - sb.WriteRune(r) + var p int + var hours int +loop: + for i, r := range s { + switch r { + case 's', 'm': + p = i + break loop + case 'h': + d, err := strconv.Atoi(s[p:i]) + if err != nil { + return 0, errors.New("time: invalid duration " + s) } - } - */ - var td time.Duration - var err error - switch s[len(s)-1] { - case 's', 'm', 'h': - td, err = time.ParseDuration(s) - case 'd': - if td, err = time.ParseDuration(s[:len(s)-1] + "h"); err == nil { - td *= 24 - } - case 'y': - if td, err = time.ParseDuration(s[:len(s)-1] + "h"); err == nil { - year := time.Date(time.Now().Year(), time.December, 31, 0, 0, 0, 0, time.Local) - days := year.YearDay() - td *= 24 * time.Duration(days) + hours += d + p = i + 1 + case 'd': + d, err := strconv.Atoi(s[p:i]) + if err != nil { + return 0, errors.New("time: invalid duration " + s) + } + hours += d * 24 + p = i + 1 + case 'y': + n, err := strconv.Atoi(s[p:i]) + if err != nil { + return 0, errors.New("time: invalid duration " + s) + } + var d int + for j := n - 1; j >= 0; j-- { + d += time.Date(time.Now().Year()+j, time.December, 31, 0, 0, 0, 0, time.Local).YearDay() + } + hours += d * 24 + p = i + 1 } } - return td, err + return time.ParseDuration(fmt.Sprintf("%dh%s", hours, s[p:])) } func (d Duration) MarshalJSON() ([]byte, error) { diff --git a/util/time/duration_test.go b/util/time/duration_test.go index 01cdd8bc..d538b449 100644 --- a/util/time/duration_test.go +++ b/util/time/duration_test.go @@ -35,15 +35,14 @@ func TestUnmarshalJSON(t *testing.T) { func TestParseDuration(t *testing.T) { var td time.Duration var err error - t.Skip() + td, err = ParseDuration("14d4h") if err != nil { t.Fatalf("ParseDuration error: %v", err) } - if td.String() != "336h0m0s" { - t.Fatalf("ParseDuration 14d != 336h0m0s : %s", td.String()) + if td.String() != "340h0m0s" { + t.Fatalf("ParseDuration 14d != 340h0m0s : %s", td.String()) } - td, err = ParseDuration("1y") if err != nil { t.Fatalf("ParseDuration error: %v", err)