diff --git a/internal/app/args.go b/internal/app/args.go index 44b0e7c7..2d10f080 100644 --- a/internal/app/args.go +++ b/internal/app/args.go @@ -113,7 +113,7 @@ func (f positiveInt) Set(raw string) error { } func parseRunTime(value string, now time.Time) (*time.Time, error) { - if duration, err := time.ParseDuration(value); err == nil { + if duration, err := durationAgo(value); err == nil { if duration < 0 { return nil, errors.New("relative duration cannot be negative") } @@ -128,6 +128,20 @@ func parseRunTime(value string, now time.Time) (*time.Time, error) { return nil, errors.New("use a date, RFC3339 timestamp, or duration such as 24h") } +// durationAgo parses a duration like time.ParseDuration, and also whole days and weeks: 7d, 2w. +func durationAgo(value string) (time.Duration, error) { + for unit, size := range map[string]time.Duration{"d": 24 * time.Hour, "w": 7 * 24 * time.Hour} { + if count, ok := strings.CutSuffix(value, unit); ok { + n, err := strconv.Atoi(count) + if err != nil { + return 0, err + } + return time.Duration(n) * size, nil + } + } + return time.ParseDuration(value) +} + // timeRange is a pair of lower and upper time bound flags. type timeRange struct { flags *pflag.FlagSet diff --git a/internal/app/args_test.go b/internal/app/args_test.go index 9af8cf61..233f23f2 100644 --- a/internal/app/args_test.go +++ b/internal/app/args_test.go @@ -19,6 +19,8 @@ func TestParseRunTime(t *testing.T) { expected time.Time }{ {"24h", now.Add(-24 * time.Hour)}, + {"7d", now.Add(-7 * 24 * time.Hour)}, + {"2w", now.Add(-14 * 24 * time.Hour)}, {"0s", now}, {"2028-01-01", time.Date(2028, 1, 1, 0, 0, 0, 0, plus2)}, {"2028-01-01T00:30:00+02:00", time.Date(2027, 12, 31, 22, 30, 0, 0, time.UTC)}, @@ -28,7 +30,7 @@ func TestParseRunTime(t *testing.T) { require.NoError(t, err) require.True(t, result.Equal(tc.expected), tc.input) } - for _, input := range []string{"", "-24h", "not-a-date", "2028-02-30"} { + for _, input := range []string{"", "-24h", "not-a-date", "2028-02-30", "-1d", "1.5w"} { _, err := parseRunTime(input, now) require.Error(t, err, input) }