temporal is immutable temporal algebra for Go. It provides bounded instant
and civil-date periods, explicit endpoint bounds, Allen relations, normalized
period sets, fixed elapsed durations, local times, circular daily intervals,
strict notation, versioned scalar/set encoding, PostgreSQL range adapters, and
bounded parsers and iterators.
The module is a Go-native successor to github.com/faustbrian/go-temporal. It
preserves useful mathematics without copying mutable or PHP-specific APIs.
go get github.com/faustbrian/go-temporalThe minimum supported toolchain is Go 1.26.6. Civil-date features use
github.com/faustbrian/go-calendar; clocks and timers deliberately remain in
clock.
start := time.Date(2026, 7, 16, 9, 0, 0, 0, time.UTC)
period, err := instant.Range(start, start.Add(90*time.Minute))
if err != nil { log.Fatal(err) }
parts, err := period.SplitForward(30*time.Minute, temporal.Limits{Steps: 10})
if err != nil { log.Fatal(err) }
set, err := instant.NewSet(temporal.Limits{}, parts...)
if err != nil { log.Fatal(err) }
dayStart, err := instant.Snap(
start, instant.Day, instant.Floor, time.UTC, timezone.Reject,
)
if err != nil { log.Fatal(err) }
fmt.Println(set.Includes(start), set.Len()) // true 1: normalization merged partsinstant.Range is closed-open. Use instant.New for another bound mode.
Instant duration is elapsed duration; calendar months are never inferred.
month, err := dateperiod.Month(2026, time.July)
if err != nil { log.Fatal(err) }
weeks, err := month.SplitDays(7, temporal.Limits{Steps: 10})
if err != nil { log.Fatal(err) }
helsinki, _ := time.LoadLocation("Europe/Helsinki")
instants, err := month.ToInstant(helsinki, timezone.Reject)
if err != nil { log.Fatal(err) }Date arithmetic delegates to calendar. Conversion uses the next civil
boundary as an exclusive instant end, so DST-short and DST-long days remain
correct.
start, _ := timeofday.Parse("22:00", temporal.Limits{})
end, _ := timeofday.Parse("02:00", temporal.Limits{})
night, err := timeofday.Between(start, end, temporal.ClosedOpen)
if err != nil { log.Fatal(err) }
set, _ := timeofday.NewIntervalSet(temporal.Limits{}, night)
offHours, err := set.Complement()
if err != nil { log.Fatal(err) }
helsinki, _ := time.LoadLocation("Europe/Helsinki")
date := calendar.MustDate(2026, time.July, 16)
instantNight, err := night.ToInstant(date, helsinki, timezone.Reject)
if err != nil { log.Fatal(err) }
fmt.Println(night.Kind(), night.Duration(), offHours.Len(), instantNight.Start())
// Circular 4h0m0s 124:00 is a distinct end boundary. Equal endpoints must be constructed as
Collapsed or FullDay; they are never guessed.
temporal: bounds, Allen relations, typed errors, and resource limits.instant: boundedtime.Timeperiods and normalized sets.dateperiod: boundedcalendar.Dateperiods and normalized sets.timeofday: local times, fixed durations, circular intervals, and sets.notation: strict ISO 8601, ISO 80000, and Bourbaki codecs.adapters/postgres: loss-checked PostgreSQL range and multirange adapters.adapters/wire: versioned format-neutral scalar and set documents.adapters/validation: deterministicvalidationrules.adapters/config: atomicconfigtext wrappers.temporaltest: exhaustive relation fixtures and set assertions.
The released postgres, temporalwire, temporalvalidation, and
temporalconfig imports remain compatibility facades for the longer of 180
days after successor availability and two subsequent stable minor releases.
The audited PHP source is pinned at
469603239dbe700739c29b4c532a90382b6cbedf. The complete behavior inventory
has a machine-checked classification and evidence pointer for every non-chart
public symbol. Deliberate divergences are in
docs/compatibility.md and
docs/migration.md. Generated compatibility evidence is
stored under compat/fixtures.
Charting is intentionally unsupported in v1. There is no temporalchart
package and no terminal/Gantt renderer in core. Every PHP chart type and option
is inventoried, and the core period/set values preserve a future renderer seam.
Full PHP-package compatibility is not claimed while this gap remains.
See the versioned Golib ecosystem index and package-family selection guidance for the shared design language this module follows.
make cohesion
make check
golib mutation --module .
golib docs check --module .
make -f verification/package.mk php-compat PHP_TEMPORAL_SOURCE=/path/to/php-temporalSee the documentation index and testing guide for the evidence model and docs/hardening.md for the current algebra audit. See SECURITY.md for hostile-input and disclosure guidance. The specification decision register separates standard-backed codec and PostgreSQL behavior from package API policy. This library does not implement the Temporal service protocol.
MIT. See LICENSE.