Skip to content

feat: Add support for negative years (BC dates) in Year field #254

@CybotTM

Description

@CybotTM

Summary

Enable support for negative years (BC dates) in the Year field for research, historical simulation, and experimental use cases.

Background

With PR #253, the Year field now uses sparse map[int]struct{} storage with expanded bounds (1 CE to MaxInt32). However, negative years (BC dates) are not yet supported.

Go's time.Time fully supports negative years:

time.Date(-44, 3, 15, 0, 0, 0, 0, time.UTC) // March 15, 44 BC (Ides of March!)

Challenges

Syntax Problem

The standard cron syntax uses - as a range separator, making negative years ambiguous:

  • "-44" would be parsed as empty start - to 44 (invalid range)

Proposed Solutions

  1. Add ~ prefix for negative years

    • ~44 = year 44 BC (-44)
    • ~100-~44 = range from 100 BC to 44 BC
    • Example: 0 0 15 3 * ~44 = midnight on March 15, 44 BC
  2. Add WithYearBounds(min, max int) method

    • Allows users to configure custom year bounds per parser
    • Example: parser.WithYearBounds(-10000, 10000) for 10000 BC to 10000 AD

Both solutions are needed: the syntax (#1) enables expressing negative years, and the bounds method (#2) enables validating them.

Proposed Implementation

// New syntax: ~ prefix for negative years
parser := NewParser(Minute | Hour | Dom | Month | Dow | Year).
    WithYearBounds(-10000, 10000)

// Ides of March, 44 BC - midnight on March 15
sched, _ := parser.Parse("0 0 15 3 * ~44")

// Range from 100 BC to 44 BC
sched, _ := parser.Parse("0 0 1 1 * ~100-~44")

Tasks

  • Update getYearRange() to parse ~ prefix as negative
  • Add WithYearBounds(min, max int) Parser method
  • Update YearBase constant or make it configurable
  • Add tests for negative year parsing
  • Add tests for year bounds configuration
  • Update documentation

Use Cases

While primarily for experimentation and research, potential use cases include:

  • Historical event simulations
  • Astronomy/calendar calculations
  • Educational tools
  • Game development with historical settings

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions