a03675113a
- .claude/agents/fn-orquestador/SKILL.md - .claude/commands/fn_claude.md - .claude/rules/INDEX.md - .claude/rules/cpp_apps.md - .claude/rules/ids_naming.md - CHANGELOG.md - apps/dag_engine/README.md - apps/dag_engine/api.go - apps/dag_engine/dags_migrated/example.yaml - apps/dag_engine/dags_migrated/example_lineage_tracking.yaml - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
80 lines
1.9 KiB
Go
80 lines
1.9 KiB
Go
package core
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// CronExplain returns a short human-readable description of a cron expression.
|
|
// Supports 5-field standard cron and @hourly/@daily/@weekly/@monthly shortcuts.
|
|
// Returns the raw expression if the pattern is not recognized.
|
|
func CronExplain(expr string) string {
|
|
expr = strings.TrimSpace(expr)
|
|
|
|
// Handle shortcuts
|
|
switch expr {
|
|
case "@hourly":
|
|
return "hourly"
|
|
case "@daily", "@midnight":
|
|
return "daily"
|
|
case "@weekly":
|
|
return "weekly"
|
|
case "@monthly":
|
|
return "monthly"
|
|
case "@yearly", "@annually":
|
|
return "yearly"
|
|
}
|
|
|
|
fields := strings.Fields(expr)
|
|
if len(fields) < 5 {
|
|
return expr
|
|
}
|
|
|
|
// Use first 5 fields (ignore optional 6th seconds/year field)
|
|
minute := fields[0]
|
|
hour := fields[1]
|
|
dom := fields[2] // day of month
|
|
month := fields[3]
|
|
dow := fields[4] // day of week
|
|
|
|
// "every N minutes": */N in minute field, rest are *
|
|
if strings.HasPrefix(minute, "*/") && dom == "*" && month == "*" && dow == "*" {
|
|
n := minute[2:]
|
|
if n == "1" {
|
|
return "every minute"
|
|
}
|
|
return fmt.Sprintf("every %s minutes", n)
|
|
}
|
|
|
|
// "every N hours": plain minute "0", */N in hour, rest are *
|
|
if strings.HasPrefix(hour, "*/") && minute == "0" && dom == "*" && month == "*" && dow == "*" {
|
|
n := hour[2:]
|
|
if n == "1" {
|
|
return "every hour"
|
|
}
|
|
return fmt.Sprintf("every %s hours", n)
|
|
}
|
|
|
|
// "daily at HH:MM": plain numbers for minute and hour, rest are *
|
|
if dom == "*" && month == "*" && dow == "*" {
|
|
m, errM := strconv.Atoi(minute)
|
|
h, errH := strconv.Atoi(hour)
|
|
if errM == nil && errH == nil {
|
|
return fmt.Sprintf("daily at %02d:%02d", h, m)
|
|
}
|
|
}
|
|
|
|
// "weekdays at HH:MM": plain minute/hour, dow == "1-5", dom/month are *
|
|
if dom == "*" && month == "*" && dow == "1-5" {
|
|
m, errM := strconv.Atoi(minute)
|
|
h, errH := strconv.Atoi(hour)
|
|
if errM == nil && errH == nil {
|
|
return fmt.Sprintf("weekdays at %02d:%02d", h, m)
|
|
}
|
|
}
|
|
|
|
// Not recognized — return raw expression
|
|
return expr
|
|
}
|