chronic

package module
v0.0.0-...-666fcc9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: BSD-3-Clause Imports: 6 Imported by: 0

README

chronic — go-ruby-chronic

Go Reference CI Coverage

A pure-Go (no cgo) reimplementation of Ruby's chronic gem — a natural-language date and time parser. It turns English phrases such as "tomorrow", "next tuesday", "3 days ago", "may 27th" or "2016-05-27" into a concrete instant (or a Span), faithfully mirroring the deterministic grammar of chronic 0.10.2without any Ruby runtime.

It is the natural-language time backend for go-embedded-ruby, but is a standalone, reusable module with no dependency on the Ruby runtime — a sibling of go-ruby-regexp (the Onigmo engine) and go-ruby-erb (the ERB compiler).

Deterministic by construction

Parse is deterministic: pass a fixed anchor via Options.Now and the result depends only on the input string, so it needs no interpreter and no wall clock. Its output is differential-tested byte-for-byte against MRI's own chronic gem.

Usage

import (
	"time"

	"github.com/go-ruby-chronic/chronic"
)

now := time.Date(2006, 8, 16, 14, 0, 0, 0, time.Local)
t, _ := chronic.Parse("tomorrow", chronic.Options{Now: now})
// t == 2006-08-17 12:00:00

Tests & coverage

go test ./... runs the unit, golden and differential-oracle suites. The CI gate enforces 100% statement coverage and builds/tests on all six 64-bit Go targets — amd64, arm64, riscv64, loong64, ppc64le, s390x.

License

BSD-3-Clause. Copyright (c) the go-ruby-chronic/chronic authors.

WebAssembly

Being pure Go (CGO=0), this library also compiles to WebAssembly — both GOOS=js GOARCH=wasm (browser / Node.js) and GOOS=wasip1 GOARCH=wasm (WASI). CI builds both targets on every push, alongside the six 64-bit native/qemu arches.

GOOS=js     GOARCH=wasm go build ./...   # browser / Node
GOOS=wasip1 GOARCH=wasm go build ./...   # WASI (wasmtime, wasmer, wasmedge, …)

Documentation

Overview

Package chronic is a pure-Go (no cgo) reimplementation of Ruby's `chronic` gem — a natural-language date and time parser. It turns English phrases such as "tomorrow", "next tuesday", "3 days ago", "may 27th" or "2016-05-27" into a concrete instant (or a Span), faithfully mirroring the deterministic grammar of chronic 0.10.2.

The entry point is Parse. It is deterministic: pass a fixed anchor via Options.Now and the result depends only on the input string, so it needs no Ruby runtime.

now := time.Date(2006, 8, 16, 14, 0, 0, 0, time.Local)
t, _ := chronic.Parse("tomorrow", chronic.Options{Now: now})
// t == 2006-08-17 12:00:00

Index

Constants

This section is empty.

Variables

View Source
var TimeLoc = time.Local

TimeLoc is the location every constructed instant lives in. It mirrors MRI's Time.local, which builds times in the process-local zone. It is a package variable so callers (and the oracle tests) can pin it to a fixed zone for reproducibility.

Functions

func Parse

func Parse(text string, opts ...Options) (time.Time, bool)

Parse parses a natural-language date/time string, returning the chosen instant and true, or the zero Time and false when nothing could be parsed. It mirrors Chronic.parse with the guess applied.

Types

type Context

type Context int

Context selects how ambiguous phrases resolve in time.

const (
	// ContextFuture (the default) reads an ambiguous phrase as the next
	// occurrence in the future.
	ContextFuture Context = iota
	// ContextPast reads an ambiguous phrase as the most recent past occurrence.
	ContextPast
)

type Guess

type Guess int

Guess selects whether Parse returns a single instant or the whole matched Span, and — for an instant — which point of the span to pick.

const (
	// GuessMiddle (the default) returns the midpoint of the matched span.
	GuessMiddle Guess = iota
	// GuessBegin returns the span's start.
	GuessBegin
	// GuessEnd returns the span's end.
	GuessEnd
	// GuessNone disables guessing; Parse then returns the Span via ParseSpan.
	GuessNone
)

type Options

type Options struct {
	// Now is the anchor instant. Leave zero to use the current time. Pin it for
	// deterministic parses.
	Now time.Time
	// Context resolves ambiguity toward the future (default) or past.
	Context Context
	// Guess selects the returned instant within the matched span.
	Guess Guess
	// AmbiguousTimeRange is the hour (1..12) an ambiguous bare time like "5" is
	// assumed to fall within (AM..PM). Zero means the default of 6. Set
	// AmbiguousTimeRangeNone to disable the assumption entirely.
	AmbiguousTimeRange     int
	AmbiguousTimeRangeNone bool
	// EndianLittle parses "03/04/2011" as day/month (d/m) rather than the
	// default month/day (m/d).
	EndianLittle bool
	// WeekStart is the first day of the week ("sunday" default, or "monday").
	WeekStart string
	// Hours24 forces 24-hour interpretation when true; set Hours24Set together
	// with Hours24=false to force 12-hour interpretation. When Hours24Set is
	// false the parser auto-detects (the gem's nil).
	Hours24    bool
	Hours24Set bool
	// AmbiguousYearFutureBias biases two-digit year expansion (default 50).
	AmbiguousYearFutureBias int
}

Options configures a parse, mirroring Chronic::Parser's options hash. The zero value is valid and matches the gem's defaults (context future, guess middle, sunday week start, ambiguous-time-range 6, endian precedence middle-then- little, ambiguous-year-future-bias 50). Now defaults to time.Now.

type Span

type Span struct {
	Begin time.Time
	End   time.Time
}

Span is a half-open range of time [Begin, End). It mirrors Chronic::Span, which subclasses Ruby's Range over Time.

func ParseSpan

func ParseSpan(text string, opts ...Options) (*Span, bool)

ParseSpan parses text and returns the whole matched Span (guess disabled), or nil and false when nothing parsed.

func (*Span) Width

func (s *Span) Width() int

Width returns the span's duration in whole seconds.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL