Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions pkg/parser/schedule_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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)
}
}

Expand Down
7 changes: 6 additions & 1 deletion pkg/parser/schedule_parser_fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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")

Expand Down
38 changes: 34 additions & 4 deletions pkg/parser/schedule_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down