chore: auto-commit (286 archivos)
- .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>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user