Documentation
¶
Overview ¶
Package kronos provides natural language date parsing for Go.
Kronos makes it easy to parse human-friendly date expressions like "tomorrow at 3pm", "next Friday", "in 2 weeks" into structured time.Time values. It's inspired by the excellent chrono JavaScript library and provides a similar feature set with a Go-idiomatic API.
Quick Start ¶
The simplest way to parse dates is using the en package convenience functions:
import "github.com/kljensen/kronos/en"
// Parse a single date
date, err := en.ParseDateSimple("tomorrow at 3pm")
// Parse all dates in text
results, err := en.ParseSimple("Meet me tomorrow or next Friday")
Builder Pattern API ¶
For more control over parsing behavior, use the builder pattern:
parser := en.New().
WithReferenceDate(refDate).
PreferPast().
DateOrder(kronos.DateOrderDMY)
results, err := parser.Parse("last Monday")
The builder provides a fluent API for configuration:
- WithReferenceDate(time.Time) - Set the reference date for relative dates
- Strict() - Enable strict parsing mode (formal patterns only)
- Casual() - Enable casual parsing mode (informal expressions, default)
- DateOrder(DateOrder) - Set date component order (MDY, DMY, YMD)
- PreferPast() - Prefer past dates when ambiguous
- PreferFuture() - Prefer future dates when ambiguous
- PreferCurrentPeriod() - Prefer current period (default)
- Timezone(string) - Set default timezone
Working with Results ¶
Each Result represents a parsed date/time expression:
for _, r := range results {
fmt.Printf("Found '%s' at position %d\n", r.Text(), r.Index())
fmt.Printf("Date: %v\n", r.Date())
// Access individual components
comp := r.Start()
if comp.IsCertain(kronos.ComponentHour) {
hour := comp.Get(kronos.ComponentHour)
fmt.Printf("Hour was mentioned: %d\n", *hour)
}
}
Component Certainty ¶
Kronos distinguishes between components that were explicitly mentioned and those that were implied from context:
results, _ := en.ParseSimple("tomorrow at 3pm")
comp := results[0].Start()
comp.IsCertain(ComponentHour) // true - "3pm" explicitly mentions hour
comp.IsCertain(ComponentYear) // false - year is implied from reference date
Date Ranges ¶
Kronos can parse date ranges with both start and end dates:
results, _ := en.ParseSimple("from Monday to Friday")
if results[0].End() != nil {
start := results[0].Start().Date()
end := results[0].End().Date()
}
Supported Expressions ¶
Relative dates:
- "yesterday", "today", "tomorrow"
- "last Monday", "next Friday"
- "3 days ago", "in 2 weeks"
- "2 hours from now"
Absolute dates:
- "March 15, 2024"
- "3/15/2024", "15/3/2024" (configurable order)
- "2024-03-15" (ISO format)
- "15th of March"
Time expressions:
- "3pm", "15:30", "3:30:45 PM"
- "noon", "midnight"
- "14:30 EST"
Combined:
- "tomorrow at 3pm"
- "March 15 at 14:30"
- "next Friday at noon"
Localization ¶
The en package provides pre-configured parsers for English:
- en.Casual - Casual US English (recognizes informal expressions)
- en.Strict - Strict US English (formal patterns only)
- en.GB - British English (DMY date order)
You can create parsers from these configurations:
parser := kronos.New(en.Casual) parser := kronos.New(en.GB).PreferPast()
Or use the convenience builders:
parser := en.New() // Casual US English parser := en.StrictParser() // Strict US English parser := en.GBParser() // British English
Architecture ¶
Kronos uses a multi-stage pipeline:
1. Parsers scan the input text for date/time patterns 2. Each match is converted to Components (year, month, day, etc.) 3. Refiners post-process results (e.g., merge "tomorrow at 3pm") 4. Final Results include matched text, components, and time.Time values
Thread Safety ¶
ParserBuilder is not thread-safe. Create a separate builder for each goroutine:
// Good: one builder per goroutine
go func() {
parser := en.New()
results, _ := parser.Parse(text)
}()
// Bad: shared builder across goroutines
parser := en.New()
go func() {
results, _ := parser.Parse(text1) // Race condition!
}()
go func() {
results, _ := parser.Parse(text2) // Race condition!
}()
Performance ¶
For best performance:
- Reuse ParserBuilder instances within a single goroutine
- Use ParseDate() instead of Parse() if you only need the first result
- Consider using strict mode to reduce parser overhead
Extensibility ¶
The parser and refiner interfaces are used internally but not part of the public API. For most use cases, the pre-configured parsers (Casual, Strict, GB) provide excellent coverage. If you need additional parsing capabilities, please open an issue on GitHub.
Example (PackageLevelParse) ¶
Example_packageLevelParse demonstrates the package-level Parse function.
package main
import (
"fmt"
"time"
"github.com/kljensen/kronos/en"
)
func main() {
// Using the new builder API
results, err := en.New().Parse("tomorrow")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
if len(results) > 0 {
// Tomorrow will be in the future
isFuture := results[0].Date().After(time.Now())
fmt.Printf("Parsed successfully: %t\n", isFuture)
}
}
Output: Parsed successfully: true
Example (ParserBuilder) ¶
Example_parserBuilder demonstrates the new builder pattern API for parsing dates.
package main
import (
"fmt"
"time"
"github.com/kljensen/kronos/en"
)
func main() {
// Basic usage with the builder pattern
refDate := time.Date(2020, 11, 15, 12, 0, 0, 0, time.UTC)
// Parse with default settings
results, err := en.New().
WithReferenceDate(refDate).
Parse("tomorrow at 3pm")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
if len(results) > 0 {
fmt.Printf("Parsed date: %s\n", results[0].Date().Format("2006-01-02 15:04"))
}
}
Output: Parsed date: 2020-11-16 15:00
Example (ParserBuilder_dateOrder) ¶
Example_parserBuilder_dateOrder demonstrates setting date order for ambiguous formats.
package main
import (
"fmt"
"time"
"github.com/kljensen/kronos"
"github.com/kljensen/kronos/en"
)
func main() {
refDate := time.Date(2020, 1, 1, 12, 0, 0, 0, time.UTC)
// Parse with US format (MDY)
date, err := en.New().
WithReferenceDate(refDate).
DateOrder(kronos.DateOrderMDY).
ParseDate("03/15/2020")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
if date != nil {
fmt.Printf("Month: %d, Day: %d\n", date.Month(), date.Day())
}
}
Output: Month: 3, Day: 15
Example (ParserBuilder_gbFormat) ¶
Example_parserBuilder_gbFormat demonstrates UK date format parsing.
package main
import (
"fmt"
"time"
"github.com/kljensen/kronos/en"
)
func main() {
refDate := time.Date(2020, 1, 1, 12, 0, 0, 0, time.UTC)
// GB format uses day/month/year
date, err := en.NewGB().
WithReferenceDate(refDate).
ParseDate("15/03/2020")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
if date != nil {
fmt.Printf("Day: %d, Month: %d\n", date.Day(), date.Month())
}
}
Output: Day: 15, Month: 3
Example (ParserBuilder_preferFuture) ¶
Example_parserBuilder_preferFuture demonstrates using PreferFuture with the builder.
package main
import (
"fmt"
"time"
"github.com/kljensen/kronos/en"
)
func main() {
refDate := time.Date(2020, 11, 15, 12, 0, 0, 0, time.UTC)
// Parse "March" with PreferFuture - should be March 2021
date, err := en.New().
WithReferenceDate(refDate).
PreferFuture().
ParseDate("March")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
if date != nil {
fmt.Printf("Year: %d, Month: %s\n", date.Year(), date.Month())
}
}
Output: Year: 2021, Month: March
Example (ParserBuilder_preferPast) ¶
Example_parserBuilder_preferPast demonstrates using PreferPast with the builder.
package main
import (
"fmt"
"time"
"github.com/kljensen/kronos/en"
)
func main() {
refDate := time.Date(2020, 11, 15, 12, 0, 0, 0, time.UTC)
// Parse "March" with PreferPast - should be March 2020
date, err := en.New().
WithReferenceDate(refDate).
PreferPast().
ParseDate("March")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
if date != nil {
fmt.Printf("Year: %d, Month: %s\n", date.Year(), date.Month())
}
}
Output: Year: 2020, Month: March
Example (ParserBuilder_strictMode) ¶
Example_parserBuilder_strictMode demonstrates strict parsing mode.
package main
import (
"fmt"
"time"
"github.com/kljensen/kronos/en"
)
func main() {
refDate := time.Date(2020, 1, 1, 12, 0, 0, 0, time.UTC)
// Strict mode validates more strictly
date, err := en.NewStrict().
WithReferenceDate(refDate).
ParseDate("2020-03-15")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
if date != nil {
fmt.Printf("Parsed: %s\n", date.Format("2006-01-02"))
}
}
Output: Parsed: 2020-03-15
Example (ParserSimple) ¶
Example_parserSimple demonstrates the simple convenience functions.
package main
import (
"fmt"
"time"
"github.com/kljensen/kronos/en"
)
func main() {
// Simple parsing with default settings and current time as reference
results, err := en.ParseSimple("tomorrow")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
if len(results) > 0 {
// Tomorrow will be in the future
isFuture := results[0].Date().After(time.Now())
fmt.Printf("Is future: %t\n", isFuture)
}
}
Output: Is future: true
Index ¶
- func InternalAddDuration(ref time.Time, duration Duration) (time.Time, error)
- func InternalGetLastWeekdayOfMonth(year int, month time.Month, weekday time.Weekday, hour int) time.Time
- func InternalGetNthWeekdayOfMonth(year int, month time.Month, weekday time.Weekday, n int, hour int) time.Time
- func InternalMergeDateTimeComponent(dateComp, timeComp *parsingComponents) *parsingComponents
- func InternalMergeDateTimeResult(dateResult, timeResult *parsingResult) *parsingResult
- func InternalNewParsingComponents(reference *referenceWithTimezone, knownComponents map[Component]int) *parsingComponents
- func InternalNewParsingContext(text string, refDate any, option *parsingOption) *parsingContext
- func InternalNewParsingResult(reference *referenceWithTimezone, index int, text string, ...) *parsingResult
- func InternalNewReferenceWithTimezone(instant time.Time, timezoneOffset *int) *referenceWithTimezone
- type AmbiguousTimezoneMap
- type Component
- type Components
- type DateOrder
- type DatePreference
- type DebugHandler
- type Duration
- type InternalParsingComponents
- type InternalParsingContext
- type InternalParsingOption
- type InternalParsingReference
- type InternalParsingResult
- type InternalParsingResultWithBoundary
- type InternalReferenceWithTimezone
- type Parser
- type ParserBuilder
- func (p *ParserBuilder) Casual() *ParserBuilder
- func (p *ParserBuilder) DateOrder(order DateOrder) *ParserBuilder
- func (p *ParserBuilder) Parse(text string) ([]Result, error)
- func (p *ParserBuilder) ParseDate(text string) (*time.Time, error)
- func (p *ParserBuilder) PreferCurrentPeriod() *ParserBuilder
- func (p *ParserBuilder) PreferFuture() *ParserBuilder
- func (p *ParserBuilder) PreferPast() *ParserBuilder
- func (p *ParserBuilder) Settings() Settings
- func (p *ParserBuilder) Strict() *ParserBuilder
- func (p *ParserBuilder) Timezone(tz string) *ParserBuilder
- func (p *ParserBuilder) WithOption(option func(*Settings)) *ParserBuilder
- func (p *ParserBuilder) WithReferenceDate(refDate time.Time) *ParserBuilder
- type Period
- type Refiner
- type Result
- type Settings
- type Timeunit
- type TimezoneAbbrMap
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func InternalAddDuration ¶
InternalAddDuration is exported for use by internal packages only. External code should not use this function directly.
It returns the date after adding the given duration to ref. It handles fractional durations by cascading remainders to smaller units. For example, 1.5 months becomes 1 month + 2 weeks. Returns an error if the duration or resulting date is out of bounds.
func InternalGetLastWeekdayOfMonth ¶
func InternalGetLastWeekdayOfMonth(year int, month time.Month, weekday time.Weekday, hour int) time.Time
InternalGetLastWeekdayOfMonth returns the date of the last occurrence of a given weekday in a given month and year (internal use only).
func InternalGetNthWeekdayOfMonth ¶
func InternalGetNthWeekdayOfMonth(year int, month time.Month, weekday time.Weekday, n int, hour int) time.Time
InternalGetNthWeekdayOfMonth returns the date of the nth occurrence of a given weekday in a given month and year (internal use only).
func InternalMergeDateTimeComponent ¶
func InternalMergeDateTimeComponent(dateComp, timeComp *parsingComponents) *parsingComponents
InternalMergeDateTimeComponent merges date and time components (internal use only).
func InternalMergeDateTimeResult ¶
func InternalMergeDateTimeResult(dateResult, timeResult *parsingResult) *parsingResult
InternalMergeDateTimeResult merges date and time results (internal use only).
func InternalNewParsingComponents ¶
func InternalNewParsingComponents(reference *referenceWithTimezone, knownComponents map[Component]int) *parsingComponents
InternalNewParsingComponents creates parsing components (internal use only).
func InternalNewParsingContext ¶
InternalNewParsingContext creates a parsing context (internal use only).
func InternalNewParsingResult ¶
func InternalNewParsingResult(reference *referenceWithTimezone, index int, text string, start, end *parsingComponents) *parsingResult
InternalNewParsingResult creates a parsing result (internal use only).
func InternalNewReferenceWithTimezone ¶
func InternalNewReferenceWithTimezone(instant time.Time, timezoneOffset *int) *referenceWithTimezone
InternalNewReferenceWithTimezone creates a reference with timezone (internal use only).
Types ¶
type AmbiguousTimezoneMap ¶
type AmbiguousTimezoneMap = data.AmbiguousTimezoneMap
AmbiguousTimezoneMap defines a timezone that has different offsets depending on whether daylight saving time (DST) is in effect.
This type is used with the builder pattern via WithOption for custom timezone handling:
customTimezones := kronos.TimezoneAbbrMap{
"ET": &kronos.AmbiguousTimezoneMap{
TimezoneOffsetDuringDst: -240,
TimezoneOffsetNonDst: -300,
DstStart: func(year int) time.Time { ... },
DstEnd: func(year int) time.Time { ... },
},
}
parser := en.New().
WithOption(func(s *kronos.Settings) {
s.TimezoneOverrides = customTimezones
})
type Component ¶
type Component string
Component represents a date/time component that can be parsed. Components are used as keys in maps, so they are string constants.
const ( // ComponentYear represents the year component ComponentYear Component = "year" ComponentMonth Component = "month" ComponentDay Component = "day" ComponentWeekday Component = "weekday" // ComponentHour represents the hour component ComponentHour Component = "hour" ComponentMinute Component = "minute" ComponentSecond Component = "second" ComponentMillisecond Component = "millisecond" ComponentMicrosecond Component = "microsecond" ComponentNanosecond Component = "nanosecond" // ComponentMeridiem represents AM/PM ComponentMeridiem Component = "meridiem" ComponentTimezoneOffset Component = "timezoneOffset" )
Date/time component constants
type Components ¶
type Components interface {
// Get returns the value of the specified component.
// Returns nil if the component is not present (neither certain nor implied).
//
// For components that are either certain or implied, this returns a pointer
// to the component's integer value. Use IsCertain to distinguish between
// certain and implied components.
//
// Example:
//
// if hour := comp.Get(kronos.ComponentHour); hour != nil {
// fmt.Printf("Hour: %d\n", *hour)
// }
Get(component Component) *int
// IsCertain returns true if the component was explicitly mentioned in the input.
// Returns false if the component was implied or is not present.
//
// This allows you to distinguish between components that were actually parsed
// from the input vs. those that were filled in by the parser based on defaults
// or the reference date.
//
// Example:
//
// // For input "tomorrow at 3pm"
// comp.IsCertain(ComponentHour) // true - "3pm" explicitly mentions hour
// comp.IsCertain(ComponentDay) // true - "tomorrow" explicitly mentions a day
// comp.IsCertain(ComponentYear) // false - year is implied from reference date
// comp.IsCertain(ComponentMinute) // false - minute is implied as 0
IsCertain(component Component) bool
// Date returns a time.Time object constructed from the components.
// This combines all certain and implied components into a concrete date/time.
//
// The returned time.Time includes:
// - All certain components (explicitly parsed from input)
// - All implied components (filled in based on reference date or defaults)
// - Timezone adjustments if a timezone was specified
//
// Example:
//
// date := comp.Date()
// fmt.Printf("Parsed date: %v\n", date)
Date() time.Time
// Tags returns metadata tags for these components.
// Tags are used internally for debugging and testing to track how components were parsed.
// For example, tags might include "result/relativeDate", "result/casualTime", "forward".
//
// This method is primarily useful for testing and debugging parser behavior.
Tags() map[string]bool
}
Components represents the individual date/time parts of a parsed expression. It provides access to components like year, month, day, hour, minute, etc., and distinguishes between components that were explicitly mentioned (certain) and those that were implied or filled in by the parser.
This interface is the primary way to inspect the details of parsed date/time values.
Component Certainty:
Each component has a certainty level:
- Certain (or Known): The component was explicitly mentioned in the input text. For example, in "March 15, 2024 at 3pm", the month (3), day (15), year (2024), and hour (15) are certain.
- Implied: The component was not mentioned but was inferred from context or defaults. For example, in "March 15", the year might be implied from the reference date, and the hour/minute/second are implied defaults (typically 12:00:00).
- Unknown: The component is not available. Get() returns nil for these.
Example:
parser := kronos.New(en.Casual)
results, _ := parser.Parse("tomorrow at 3pm")
comp := results[0].Start()
// Check if hour was explicitly mentioned
if comp.IsCertain(kronos.ComponentHour) {
hour := comp.Get(kronos.ComponentHour)
fmt.Printf("Hour was mentioned: %d\n", *hour)
}
// Get year (likely implied, not explicitly mentioned in "tomorrow")
if year := comp.Get(kronos.ComponentYear); year != nil {
fmt.Printf("Year: %d (certain=%v)\n", *year, comp.IsCertain(kronos.ComponentYear))
}
// Convert to time.Time
date := comp.Date()
type DateOrder ¶
type DateOrder int
DateOrder represents the order of date components in ambiguous formats.
type DatePreference ¶
type DatePreference int
DatePreference specifies how ambiguous dates (with missing components) should be resolved. This controls whether dates like "March 15" (without year) or "10:00" (without date) should be interpreted as being in the past, future, or current period relative to the reference time.
const ( // PreferCurrentPeriod (default) chooses the date in the current period. // For dates with missing year: chooses the current year. // For times with missing date: chooses the current day. // Example: If reference is Feb 15, 2015 15:30 // - "March" → March 2015 (current year) // - "10:00" → Feb 15, 2015 10:00 (current day, even if past) PreferCurrentPeriod DatePreference = iota // PreferPast chooses dates in the past. // For dates with missing year: if the date would be in the future, use previous year. // For times with missing date: if the time would be in the future, use previous day. // Example: If reference is Feb 15, 2015 15:30 // - "March" → March 2014 (last March, in the past) // - "10:00" → Feb 15, 2015 10:00 (earlier today) // - "18:00" → Feb 14, 2015 18:00 (yesterday, since 18:00 today hasn't happened yet) PreferPast // PreferFuture chooses dates in the future. // For dates with missing year: if the date would be in the past, use next year. // For times with missing date: if the time would be in the past, use next day. // Example: If reference is Feb 15, 2015 15:30 // - "March" → March 2015 (next March, in the future) // - "10:00" → Feb 16, 2015 10:00 (tomorrow morning, since 10:00 already passed today) // - "18:00" → Feb 15, 2015 18:00 (later today) PreferFuture )
type DebugHandler ¶
type DebugHandler func(message string)
DebugHandler is a function that handles debug events. It receives a debug message for logging or analysis.
This type is used with the builder pattern via WithOption for debug logging:
parser := en.New().
WithOption(func(s *kronos.Settings) {
s.DebugHandler = func(msg string) {
log.Printf("DEBUG: %s", msg)
}
})
type Duration ¶
Duration represents a directed time duration as a set of values by timeunits. Positive values mean the duration goes into the future. Duration supports fractional values (e.g., 1.5 months).
func InternalReverseDuration ¶
InternalReverseDuration is exported for use by internal packages only. External code should not use this function directly.
It returns the reversed duration (e.g., back into the past instead of future). All values in the duration are negated.
type InternalParsingComponents ¶
type InternalParsingComponents = parsingComponents
InternalParsingComponents is an alias for parsingComponents, allowing internal packages to use the unexported type.
type InternalParsingContext ¶
type InternalParsingContext = parsingContext
InternalParsingContext is an alias for parsingContext, allowing internal packages to use the unexported type.
type InternalParsingOption ¶
type InternalParsingOption = parsingOption
InternalParsingOption is an alias for parsingOption, allowing internal packages to use the unexported type.
type InternalParsingReference ¶
type InternalParsingReference = parsingReference
InternalParsingReference is an alias for parsingReference, allowing internal packages to use the unexported type.
type InternalParsingResult ¶
type InternalParsingResult = parsingResult
InternalParsingResult is an alias for parsingResult, allowing internal packages to use the unexported type.
type InternalParsingResultWithBoundary ¶
type InternalParsingResultWithBoundary = parsingResultWithBoundary
InternalParsingResultWithBoundary is an alias for parsingResultWithBoundary, allowing internal packages to use the unexported type.
type InternalReferenceWithTimezone ¶
type InternalReferenceWithTimezone = referenceWithTimezone
InternalReferenceWithTimezone is an alias for referenceWithTimezone, allowing internal packages to use the unexported type.
type Parser ¶
Parser is the public interface for implementing custom parsers. Use this when adding support for new languages or date formats.
Example:
type MyParser struct{}
func (p *MyParser) Pattern(ctx parser.Context) *regexp.Regexp { ... }
func (p *MyParser) Extract(ctx parser.Context, match []string) any { ... }
type ParserBuilder ¶
type ParserBuilder struct {
// contains filtered or unexported fields
}
ParserBuilder is the main entry point for configuring and executing date parsing. It provides a fluent API for setting up parsing options and executing the parse. Use New() to create a new parser builder, configure it with builder methods, then call Parse() or ParseDate() to execute the parsing.
Thread Safety: ParserBuilder is not thread-safe and should not be shared across goroutines. Each goroutine should create its own ParserBuilder instance.
Mutability: ParserBuilder is mutable. Calling configuration methods (WithReferenceDate, Strict, PreferPast, etc.) modifies the builder's state and returns the same builder instance to enable method chaining. If you need different configurations, create separate ParserBuilder instances.
Example:
parser := kronos.New(en.Casual).
WithReferenceDate(time.Now()).
Strict().
PreferPast()
result := parser.Parse("last Monday")
func New ¶
func New(c *chrono.Chrono) *ParserBuilder
New creates a new ParserBuilder with the given Chrono configuration. This is the main entry point for the builder pattern API.
Example:
parser := kronos.New(en.Casual)
func (*ParserBuilder) Casual ¶
func (p *ParserBuilder) Casual() *ParserBuilder
Casual enables casual parsing mode (this is the default). In casual mode, the parser accepts informal expressions and is more lenient.
func (*ParserBuilder) DateOrder ¶
func (p *ParserBuilder) DateOrder(order DateOrder) *ParserBuilder
DateOrder sets the order of date components in ambiguous formats. Use DateOrderMDY for US format (12/31/2020), DateOrderDMY for European format (31/12/2020), or DateOrderYMD for ISO format (2020/12/31).
func (*ParserBuilder) Parse ¶
func (p *ParserBuilder) Parse(text string) ([]Result, error)
Parse executes the parser on the given text and returns all found date/time results. Returns an error if the settings are invalid or parsing fails.
func (*ParserBuilder) ParseDate ¶
func (p *ParserBuilder) ParseDate(text string) (*time.Time, error)
ParseDate is a shortcut for calling Parse and returning the first result's date. Returns nil if no results are found or an error occurs.
func (*ParserBuilder) PreferCurrentPeriod ¶
func (p *ParserBuilder) PreferCurrentPeriod() *ParserBuilder
PreferCurrentPeriod configures the parser to prefer dates in the current period. This is the default behavior.
func (*ParserBuilder) PreferFuture ¶
func (p *ParserBuilder) PreferFuture() *ParserBuilder
PreferFuture configures the parser to prefer future dates when ambiguous. For example, "March" in November would be interpreted as next March.
func (*ParserBuilder) PreferPast ¶
func (p *ParserBuilder) PreferPast() *ParserBuilder
PreferPast configures the parser to prefer past dates when ambiguous. For example, "March" in November would be interpreted as last March.
func (*ParserBuilder) Settings ¶
func (p *ParserBuilder) Settings() Settings
Settings returns a copy of the current settings for inspection. This is useful for advanced use cases that need to examine or validate settings. Note: Modifying the returned Settings will not affect the builder.
Example:
parser := kronos.New(en.Casual).PreferFuture()
settings := parser.Settings()
fmt.Printf("Preference: %v\n", settings.PreferDatesFrom)
func (*ParserBuilder) Strict ¶
func (p *ParserBuilder) Strict() *ParserBuilder
Strict enables strict parsing mode. In strict mode, the parser validates more strictly and rejects ambiguous dates.
func (*ParserBuilder) Timezone ¶
func (p *ParserBuilder) Timezone(tz string) *ParserBuilder
Timezone sets the default timezone for parsing. This timezone is used when no timezone is specified in the input.
func (*ParserBuilder) WithOption ¶
func (p *ParserBuilder) WithOption(option func(*Settings)) *ParserBuilder
WithOption applies an advanced configuration option to the parser. This allows fine-grained control over parsing behavior by directly modifying the Settings struct.
Example:
parser := kronos.New(en.Casual).
WithOption(func(s *kronos.Settings) {
s.TimezoneOverrides = customTimezones
s.DebugHandler = debugFunc
})
func (*ParserBuilder) WithReferenceDate ¶
func (p *ParserBuilder) WithReferenceDate(refDate time.Time) *ParserBuilder
WithReferenceDate sets the reference date for relative date calculations. This date is used as the basis for expressions like "tomorrow", "next week", etc.
type Period ¶
type Period int
Period represents the granularity of a parsed date/time expression. It indicates the finest level of precision explicitly mentioned in the input. For example:
- "2020" has year-level precision
- "March 2020" has month-level precision
- "yesterday" has day-level precision
- "10:30" has time-level precision
const ( // PeriodUnknown indicates the period could not be determined. PeriodUnknown Period = iota // PeriodYear represents year-level precision (e.g., "2020", "last year"). PeriodYear // PeriodMonth represents month-level precision (e.g., "March", "3 months ago"). PeriodMonth // PeriodWeek represents week-level precision (e.g., "last week", "2 weeks ago"). PeriodWeek // PeriodDay represents day-level precision (e.g., "yesterday", "March 15"). PeriodDay // PeriodTime represents time-level precision (e.g., "10:30", "2 hours ago"). PeriodTime )
func InternalDeterminePeriodFromDuration ¶
InternalDeterminePeriodFromDuration determines period from duration (internal use only).
type Refiner ¶
Refiner is the public interface for implementing custom refiners. Use this when adding custom post-processing logic.
Example:
type MyRefiner struct{}
func (r *MyRefiner) Refine(ctx parser.Context, results []parser.Result) []parser.Result { ... }
type Result ¶
type Result interface {
// Text returns the matched text from the input.
// This is the substring that was recognized as a date/time expression.
//
// Example: For input "tomorrow at 3pm", this might return "tomorrow at 3pm"
Text() string
// Index returns the position in the input text where this result was found.
// The index is 0-based and represents the starting position of the matched text.
//
// Example: For input "Meet me tomorrow", this would return 8
Index() int
// Date returns a time.Time object created from the start components.
// This is a convenience method equivalent to calling Start().Date().
// For date ranges, this returns the start date of the range.
//
// The returned time.Time includes all parsed and implied components.
// Components that were not mentioned are filled in with reasonable defaults
// based on the reference date.
Date() time.Time
// Start returns the starting date/time components.
// For a single date/time (not a range), this contains all the parsed information.
// For a date range, this represents the beginning of the range.
//
// Use the Components interface to inspect individual date/time parts
// and determine which were explicitly mentioned vs. implied.
Start() Components
// End returns the ending date/time components for a range.
// Returns nil for a single date/time (not a range).
//
// Example: For "from Monday to Friday", Start() returns Monday's components
// and End() returns Friday's components.
End() Components
// Tags returns metadata tags for this result.
// Tags are used internally for debugging and testing to track how a result was parsed.
// For example, tags might include "parser/iso", "refiner/merged", "result/relativeDate".
//
// This method is primarily useful for testing and debugging parser behavior.
Tags() map[string]bool
}
Result represents a parsed date/time expression found in text. It provides access to the matched text, its position, and the parsed date/time value. A Result can represent either a single date/time or a range (with Start and End components).
This is the primary interface for working with parsed results in the new builder-based API. It exposes only what users need while hiding internal implementation details.
Example:
parser := kronos.New(en.Casual)
results, _ := parser.Parse("Meet me tomorrow at 3pm")
for _, r := range results {
fmt.Printf("Found '%s' at index %d\n", r.Text(), r.Index())
fmt.Printf("Date: %v\n", r.Date())
if r.Start().IsCertain(kronos.ComponentHour) {
hour := r.Start().Get(kronos.ComponentHour)
fmt.Printf("Hour explicitly mentioned: %d\n", *hour)
}
}
type Settings ¶
type Settings struct {
// Date interpretation
DateOrder DateOrder // Order of date components (MDY, DMY, YMD)
PreferDatesFrom DatePreference // Past, Future, CurrentPeriod
// Timezone handling
Timezone string // Default timezone name (e.g., "UTC", "America/New_York")
// Parsing behavior
StrictParsing bool // Validate strictly - reject ambiguous dates
// Advanced configuration
TimezoneOverrides TimezoneAbbrMap // Custom timezone abbreviations
DebugHandler DebugHandler // Debug callback for parsing events
}
Settings contains all configuration for date parsing. It provides a comprehensive way to customize parsing behavior.
Most users should use the fluent builder API for common options:
parser := en.New().
DateOrder(kronos.DateOrderDMY).
PreferFuture().
Strict()
For advanced options, use WithOption to modify settings directly:
parser := en.New().
WithOption(func(s *kronos.Settings) {
s.TimezoneOverrides = customTimezones
s.DebugHandler = debugFunc
})
func DefaultSettings ¶
func DefaultSettings() Settings
DefaultSettings returns sensible default settings that maintain backward compatibility with existing behavior.
type Timeunit ¶
type Timeunit string
Timeunit represents a unit of time for calculations and operations. This type is used as a key in the Duration map type for specifying time durations.
Note: While Timeunit is part of the public API (used by Duration), it is primarily an implementation detail. Future versions may move this to a more restricted scope while maintaining backward compatibility for Duration operations.
const ( // TimeunitDecade represents a decade (10 years) TimeunitDecade Timeunit = "decade" TimeunitYear Timeunit = "year" TimeunitQuarter Timeunit = "quarter" TimeunitMonth Timeunit = "month" // TimeunitWeek represents a week (7 days) TimeunitWeek Timeunit = "week" TimeunitDay Timeunit = "day" // TimeunitHour represents an hour TimeunitHour Timeunit = "hour" TimeunitMinute Timeunit = "minute" TimeunitSecond Timeunit = "second" TimeunitMillisecond Timeunit = "millisecond" TimeunitMicrosecond Timeunit = "microsecond" TimeunitNanosecond Timeunit = "nanosecond" )
Time unit constants for use with Duration type. These constants are required for working with Duration maps.
Example:
duration := kronos.Duration{
kronos.TimeunitDay: 5,
kronos.TimeunitHour: 3,
}
type TimezoneAbbrMap ¶
type TimezoneAbbrMap = data.TimezoneAbbrMap
TimezoneAbbrMap maps timezone abbreviations to their offsets. Values can be either a simple offset (in minutes) or an AmbiguousTimezoneMap for timezones that observe DST.
This type is used with the builder pattern via WithOption for custom timezone handling:
customTimezones := kronos.TimezoneAbbrMap{
"CUSTOM": 123, // UTC+2:03
"TEST": -456, // UTC-7:36
}
parser := en.New().
WithOption(func(s *kronos.Settings) {
s.TimezoneOverrides = customTimezones
})
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package en provides English language support for Chrono.
|
Package en provides English language support for Chrono. |
|
examples
|
|
|
basic
command
Package main demonstrates basic usage of the kronos date parser.
|
Package main demonstrates basic usage of the kronos date parser. |
|
british
command
Package main demonstrates British English date parsing.
|
Package main demonstrates British English date parsing. |
|
builder_api
command
Package main demonstrates the builder API for kronos.
|
Package main demonstrates the builder API for kronos. |
|
components
command
Package main demonstrates working with date/time components.
|
Package main demonstrates working with date/time components. |
|
configured
command
Package main demonstrates using the ParserBuilder to configure parsing behavior.
|
Package main demonstrates using the ParserBuilder to configure parsing behavior. |
|
ranges
command
Package main demonstrates working with date ranges.
|
Package main demonstrates working with date ranges. |
|
chrono
Package chrono provides the internal Advanced API structures for Kronos.
|
Package chrono provides the internal Advanced API structures for Kronos. |
|
common/parsers
Package parsers provides shared utilities and parsers for date/time parsing.
|
Package parsers provides shared utilities and parsers for date/time parsing. |
|
common/refiners
Package refiners provides common refiner utilities for post-processing parsing results.
|
Package refiners provides common refiner utilities for post-processing parsing results. |
|
en/data
Package data provides English language dictionaries, patterns, and parsing functions.
|
Package data provides English language dictionaries, patterns, and parsing functions. |
|
en/refiners
Package refiners provides English-specific refiners for post-processing parsing results.
|
Package refiners provides English-specific refiners for post-processing parsing results. |
|
helpers
Package helpers provides internal utility functions for kronos date parsing.
|
Package helpers provides internal utility functions for kronos date parsing. |
|
parsing
Package parsing contains internal parsing implementation types for kronos.
|
Package parsing contains internal parsing implementation types for kronos. |
|
Package parser defines the interfaces for implementing custom parsers and refiners in Kronos.
|
Package parser defines the interfaces for implementing custom parsers and refiners in Kronos. |