Configure the Cron instance behavior using functional options passed to New().
// Option represents a modification to the default behavior of a Cron
type Option func(*Cron)Options are functions that modify a Cron instance during construction. Multiple options can be combined.
Set the timezone for schedule interpretation.
// WithLocation overrides the timezone of the cron instance.
// All schedules will be interpreted in this timezone unless overridden
// with CRON_TZ= prefix.
func WithLocation(loc *time.Location) OptionParameters:
loc *time.Location - Timezone locationUsage:
import (
"time"
"github.com/robfig/cron/v3"
)
// Use UTC timezone
c := cron.New(cron.WithLocation(time.UTC))
c.AddFunc("0 6 * * *", func() {
fmt.Println("6am UTC")
})
// Use specific timezone
nyc, _ := time.LoadLocation("America/New_York")
c := cron.New(cron.WithLocation(nyc))
c.AddFunc("0 6 * * *", func() {
fmt.Println("6am New York time")
})
// Default is time.Local
c := cron.New() // Uses local machine timezonePer-Schedule Override:
// Cron uses America/New_York by default
nyc, _ := time.LoadLocation("America/New_York")
c := cron.New(cron.WithLocation(nyc))
// This job uses New York time
c.AddFunc("0 6 * * *", func() { fmt.Println("6am NYC") })
// This job overrides with Tokyo time
c.AddFunc("CRON_TZ=Asia/Tokyo 0 6 * * *", func() { fmt.Println("6am Tokyo") })Enable seconds field in cron specifications.
// WithSeconds overrides the parser to include a required seconds field
// as the first field. This creates a 6-field Quartz-compatible format.
func WithSeconds() OptionUsage:
// Standard cron: 5 fields (minute hour day month weekday)
c := cron.New()
c.AddFunc("30 * * * *", func() { fmt.Println("At 30 minutes") })
// With seconds: 6 fields (second minute hour day month weekday)
c := cron.New(cron.WithSeconds())
c.AddFunc("0 30 * * * *", func() { fmt.Println("At 30 minutes, 0 seconds") })
c.AddFunc("*/5 * * * * *", func() { fmt.Println("Every 5 seconds") })
// Error: spec must have 6 fields when WithSeconds is used
id, err := c.AddFunc("30 * * * *", func() {}) // Returns errorEquivalent to:
c := cron.New(cron.WithParser(cron.NewParser(
cron.Second | cron.Minute | cron.Hour |
cron.Dom | cron.Month | cron.Dow | cron.Descriptor,
)))Use a custom parser for job schedules.
// WithParser overrides the parser used for interpreting job schedules.
// Allows full control over which fields are required/optional.
func WithParser(p ScheduleParser) OptionType Definitions:
type ScheduleParser interface {
Parse(spec string) (Schedule, error)
}Usage:
// Optional seconds field (5 or 6 fields accepted)
parser := cron.NewParser(
cron.SecondOptional | cron.Minute | cron.Hour |
cron.Dom | cron.Month | cron.Dow | cron.Descriptor,
)
c := cron.New(cron.WithParser(parser))
// Both work
c.AddFunc("30 * * * *", func() {}) // 5 fields, seconds default to 0
c.AddFunc("0 30 * * * *", func() {}) // 6 fields, seconds explicit
// Parser without descriptors
parser := cron.NewParser(
cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow,
)
c := cron.New(cron.WithParser(parser))
c.AddFunc("30 * * * *", func() {}) // Works
c.AddFunc("@hourly", func() {}) // Error: descriptors not allowed
// Parser with only date fields
dateParser := cron.NewParser(cron.Dom | cron.Month | cron.Dow)
c := cron.New(cron.WithParser(dateParser))
c.AddFunc("15 3 *", func() {}) // 15th day, March, any weekdayApply job wrappers to all jobs added to the cron.
// WithChain specifies Job wrappers to apply to all jobs added to this cron.
// Job wrappers add cross-cutting behavior like panic recovery, logging, etc.
func WithChain(wrappers ...JobWrapper) OptionType Definitions:
type JobWrapper func(Job) JobUsage:
import (
"log"
"os"
"github.com/robfig/cron/v3"
)
logger := cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))
// Apply wrappers to all jobs
c := cron.New(cron.WithChain(
cron.Recover(logger), // Recover from panics
cron.DelayIfStillRunning(logger), // Wait if previous run isn't done
))
// All jobs get wrapped automatically
c.AddFunc("@every 5s", func() {
// If this panics, it will be recovered and logged
// If it's still running after 5s, next execution waits
doWork()
})Default Chain:
// By default, New() creates a chain that recovers panics
c := cron.New() // Equivalent to cron.New(cron.WithChain(cron.Recover(cron.DefaultLogger)))
// To disable panic recovery
c := cron.New(cron.WithChain()) // Empty chain, no wrappersMultiple Wrappers:
// Wrappers are applied in order
c := cron.New(cron.WithChain(
wrapper1, // Applied first (outermost)
wrapper2,
wrapper3, // Applied last (innermost)
))
// Equivalent to: wrapper1(wrapper2(wrapper3(job)))Set a custom logger for the cron scheduler.
// WithLogger uses the provided logger for cron operations.
// The logger must implement the Logger interface.
func WithLogger(logger Logger) OptionType Definitions:
type Logger interface {
Info(msg string, keysAndValues ...interface{})
Error(err error, msg string, keysAndValues ...interface{})
}Usage:
import (
"log"
"os"
"github.com/robfig/cron/v3"
)
// Verbose logging (logs everything)
logger := cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))
c := cron.New(cron.WithLogger(logger))
// Quiet logging (errors only)
logger := cron.PrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))
c := cron.New(cron.WithLogger(logger))
// No logging
c := cron.New(cron.WithLogger(cron.DiscardLogger))
// Default logger (writes to stdout)
c := cron.New() // Uses cron.DefaultLoggerMultiple options can be combined:
import (
"log"
"os"
"time"
"github.com/robfig/cron/v3"
)
func main() {
// Setup logger
logger := cron.VerbosePrintfLogger(
log.New(os.Stdout, "cron: ", log.LstdFlags),
)
// Setup timezone
nyc, _ := time.LoadLocation("America/New_York")
// Create cron with multiple options
c := cron.New(
cron.WithLocation(nyc),
cron.WithSeconds(),
cron.WithLogger(logger),
cron.WithChain(
cron.Recover(logger),
cron.SkipIfStillRunning(logger),
),
)
// Add jobs
c.AddFunc("0 30 9 * * *", func() {
fmt.Println("Daily at 9:30:00 AM NYC time")
})
c.Start()
defer c.Stop()
select {}
}When New() is called without options, the defaults are:
c := cron.New()
// Equivalent to:
c := cron.New(
cron.WithLocation(time.Local), // Local machine timezone
cron.WithParser(standardParser), // 5-field standard cron format
cron.WithChain(
cron.Recover(cron.DefaultLogger), // Recover panics, log to stdout
),
cron.WithLogger(cron.DefaultLogger), // Log errors to stdout
)The standard parser accepts:
logger := cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))
c := cron.New(
cron.WithLocation(time.UTC), // Use UTC for consistency
cron.WithLogger(logger), // Enable logging
cron.WithChain(
cron.Recover(logger), // Always recover panics
cron.SkipIfStillRunning(logger), // Prevent overlapping executions
),
)// Verbose logging with seconds field for testing
logger := cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))
c := cron.New(
cron.WithSeconds(), // Easier to test with seconds
cron.WithLogger(logger), // See all operations
cron.WithChain(
cron.Recover(logger), // Recover and log panics
),
)// No logging, no panic recovery, use defaults
c := cron.New(
cron.WithLogger(cron.DiscardLogger),
cron.WithChain(), // No wrappers
)// 6-field format with optional descriptors
parser := cron.NewParser(
cron.Second | cron.Minute | cron.Hour |
cron.Dom | cron.Month | cron.Dow | cron.Descriptor,
)
c := cron.New(cron.WithParser(parser))Options are applied in the order they're provided:
// Later options override earlier ones
c := cron.New(
cron.WithLocation(time.UTC),
cron.WithLocation(nyc), // This takes effect
)However, it's better to provide each option only once for clarity.