or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration-options.mdcore-scheduler.mdindex.mdjob-management.mdjob-wrappers.mdlogging.mdschedule-parsing.mdschedule-types.md
tile.json

configuration-options.mddocs/

Configuration Options

Configure the Cron instance behavior using functional options passed to New().

Option Type

// 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.

Available Options

WithLocation

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) Option

Parameters:

  • loc *time.Location - Timezone location

Usage:

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 timezone

Per-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") })

WithSeconds

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() Option

Usage:

// 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 error

Equivalent to:

c := cron.New(cron.WithParser(cron.NewParser(
    cron.Second | cron.Minute | cron.Hour |
    cron.Dom | cron.Month | cron.Dow | cron.Descriptor,
)))

WithParser

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) Option

Type 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 weekday

WithChain

Apply 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) Option

Type Definitions:

type JobWrapper func(Job) Job

Usage:

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 wrappers

Multiple 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)))

WithLogger

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) Option

Type 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.DefaultLogger

Combining Options

Multiple 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 {}
}

Default Configuration

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:

  • 5-field cron expressions (minute hour day month weekday)
  • Descriptors (@hourly, @daily, @weekly, @monthly, @yearly)
  • Intervals (@every <duration>)
  • Timezone prefixes (CRON_TZ=<location>, TZ=<location>)

Configuration Best Practices

Production Configuration

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
    ),
)

Development Configuration

// 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
    ),
)

Minimal Configuration

// No logging, no panic recovery, use defaults
c := cron.New(
    cron.WithLogger(cron.DiscardLogger),
    cron.WithChain(), // No wrappers
)

Custom Parser Configuration

// 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))

Configuration Order

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.