diff --git a/pkg/parser/schedule_parser.go b/pkg/parser/schedule_parser.go index c543b5ce802..876baade7b3 100644 --- a/pkg/parser/schedule_parser.go +++ b/pkg/parser/schedule_parser.go @@ -530,8 +530,8 @@ func (p *ScheduleParser) parseInterval() (string, error) { } // Validate unit before checking minimum duration - if unit != "minutes" && unit != "hours" { - return "", fmt.Errorf("unsupported interval unit '%s', use 'minutes' or 'hours'", unit) + if unit != "minutes" && unit != "hours" && unit != "days" { + return "", fmt.Errorf("unsupported interval unit '%s', use 'minutes', 'hours', or 'days'", unit) } // Validate minimum duration of 5 minutes @@ -541,6 +541,8 @@ func (p *ScheduleParser) parseInterval() (string, error) { totalMinutes = interval case "hours": totalMinutes = interval * 60 + case "days": + totalMinutes = interval * 24 * 60 } if totalMinutes < 5 { @@ -554,8 +556,16 @@ func (p *ScheduleParser) parseInterval() (string, error) { case "hours": // every N hours -> FUZZY:HOURLY/N (fuzzy hourly interval with scattering) return fmt.Sprintf("FUZZY:HOURLY/%d * * *", interval), nil + case "days": + // every N days -> daily at midnight, repeated N times + // For single day, use daily. For multiple days, use interval in days + if interval == 1 { + return "0 0 * * *", nil // daily + } + // Convert days to day-of-month interval for cron expression + return fmt.Sprintf("0 0 */%d * *", interval), nil default: - return "", fmt.Errorf("unsupported interval unit '%s', use 'minutes' or 'hours'", unit) + return "", fmt.Errorf("unsupported interval unit '%s', use 'minutes', 'hours', or 'days'", unit) } } diff --git a/pkg/parser/schedule_parser_fuzz_test.go b/pkg/parser/schedule_parser_fuzz_test.go index c6937c752af..46095256ea1 100644 --- a/pkg/parser/schedule_parser_fuzz_test.go +++ b/pkg/parser/schedule_parser_fuzz_test.go @@ -67,6 +67,12 @@ func FuzzScheduleParser(f *testing.F) { f.Add("every 2 hours") f.Add("every 6 hours") f.Add("every 12 hours") + f.Add("every 1 day") + f.Add("every 2 days") + f.Add("every 3 days") + f.Add("every 7 days") + f.Add("every 10 days") + f.Add("every 14 days") // Interval schedules (short duration format) f.Add("every 5m") @@ -141,7 +147,6 @@ func FuzzScheduleParser(f *testing.F) { f.Add("every 2h at noon") // Invalid interval units - f.Add("every 10 days") f.Add("every 2 weeks") f.Add("every 1 month") diff --git a/pkg/parser/schedule_parser_test.go b/pkg/parser/schedule_parser_test.go index cd3af29dad0..ea468e9aa8c 100644 --- a/pkg/parser/schedule_parser_test.go +++ b/pkg/parser/schedule_parser_test.go @@ -549,10 +549,40 @@ func TestParseSchedule(t *testing.T) { errorSubstring: "invalid interval", }, { - name: "invalid interval unit", - input: "every 10 days", - shouldError: true, - errorSubstring: "unsupported interval unit", + name: "every 2 days", + input: "every 2 days", + expectedCron: "0 0 */2 * *", + expectedOrig: "every 2 days", + }, + { + name: "every 3 days", + input: "every 3 days", + expectedCron: "0 0 */3 * *", + expectedOrig: "every 3 days", + }, + { + name: "every 7 days", + input: "every 7 days", + expectedCron: "0 0 */7 * *", + expectedOrig: "every 7 days", + }, + { + name: "every 10 days", + input: "every 10 days", + expectedCron: "0 0 */10 * *", + expectedOrig: "every 10 days", + }, + { + name: "every 14 days", + input: "every 14 days", + expectedCron: "0 0 */14 * *", + expectedOrig: "every 14 days", + }, + { + name: "every 1 day", + input: "every 1 day", + expectedCron: "0 0 * * *", + expectedOrig: "every 1 day", }, { name: "weekly without on",