timenow is a small Go library and CLI for giving agents reliable local-time
context. It returns both structured machine-readable time data and concise
strings for model prompts or spoken readouts.
The module path is:
github.com/petesmithofficial/timenowUse the structured snapshot when you are storing, logging, comparing, or passing time context between systems. It includes ISO timestamps, Unix seconds, IANA location, time-zone abbreviation, UTC offset, calendar fields, day period, and optional time-zone comparisons.
Use Prompt() or CurrentPrompt() when you are grounding an LLM turn. This
format includes the time zone and UTC offset because those details help models
avoid ambiguous time reasoning.
Use PromptForSpeech() or CurrentSpeechPrompt() when the text will be read
aloud. This format omits time-zone abbreviations and UTC offsets, uses ordinal
dates, and separates thoughts with full stops.
Example prompt context:
Current local time: Thursday, 25 June 2026 at 2:30 PM AEST (Australia/Brisbane, UTC+10:00). It is afternoon today.
Example speech context:
Today is Thursday 25th of June 2026. The local time is 2:30 PM. It is afternoon.
go get github.com/petesmithofficial/timenowFor the CLI:
go install github.com/petesmithofficial/timenow/cmd/timenow@latestFrom a checkout:
go build -o timenow ./cmd/timenow# Human-readable local time using the machine's local time zone.
timenow
# One-line prompt context for an agent turn.
timenow --format prompt --timezone Australia/Brisbane
# TTS-friendly readout context without timezone detail.
timenow --format speech --timezone Australia/Brisbane
# Structured JSON with extra time-zone comparisons.
timenow --format json \
--timezone Australia/Brisbane \
--compare UTC,America/New_York
# Reproducible output for a fixed instant.
timenow --format speech \
--timezone Australia/Brisbane \
--at 2026-06-25T04:30:15Z
# Unix seconds are accepted for fixed instants.
timenow --format json --timezone UTC --at 1782361815Flags:
| Flag | Alias | Description | Default |
|---|---|---|---|
--format |
-f |
human, prompt, speech, readout, or json |
human |
--timezone |
--tz |
IANA time zone such as Australia/Brisbane; UTC is also accepted |
Local |
--compare |
Comma-separated IANA zones to include as comparisons | none | |
--at |
Fixed instant as RFC3339/RFC3339Nano or Unix seconds | current time |
readout is accepted as an alias for speech.
package main
import (
"fmt"
"log"
"github.com/petesmithofficial/timenow/pkg/timenow"
)
func main() {
snapshot, err := timenow.Current(timenow.Options{
TimeZone: "Australia/Brisbane",
})
if err != nil {
log.Fatal(err)
}
fmt.Println(snapshot.Prompt())
fmt.Println(snapshot.PromptForSpeech())
}Convenience functions:
prompt, err := timenow.CurrentPrompt(timenow.Options{
TimeZone: "Australia/Brisbane",
})
speechPrompt, err := timenow.CurrentSpeechPrompt(timenow.Options{
TimeZone: "Australia/Brisbane",
})Structured snapshots:
snapshot, err := timenow.Current(timenow.Options{
TimeZone: "Australia/Brisbane",
CompareZones: []string{"UTC", "America/New_York"},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(snapshot.LocalISO)
fmt.Println(snapshot.UTCISO)
fmt.Println(snapshot.TimeZone)
fmt.Println(snapshot.UTCOffset)
fmt.Println(snapshot.SpeechDate)
fmt.Println(snapshot.SpeechPrompt)
fmt.Println(snapshot.Comparisons[0].LocalISO)Deterministic snapshots:
instant := time.Date(2026, 6, 25, 4, 30, 15, 0, time.UTC)
snapshot, err := timenow.SnapshotAt(instant, timenow.Options{
TimeZone: "Australia/Brisbane",
})Clock injection:
clock := timenow.ClockFunc(func() time.Time {
return time.Date(2026, 6, 25, 4, 30, 15, 0, time.UTC)
})
snapshot, err := timenow.Current(timenow.Options{
Clock: clock,
TimeZone: "UTC",
})Core API:
type Clock interface {
Now() time.Time
}
type Options struct {
Clock Clock
TimeZone string
CompareZones []string
}
func Current(opts Options) (Snapshot, error)
func CurrentPrompt(opts Options) (string, error)
func CurrentSpeechPrompt(opts Options) (string, error)
func SnapshotAt(instant time.Time, opts Options) (Snapshot, error)
func Convert(instant time.Time, zoneName string, relativeTo time.Time) (ZoneTime, error)
func (s Snapshot) Prompt() string
func (s Snapshot) PromptForSpeech() string
func (s Snapshot) Human() stringImportant snapshot fields:
type Snapshot struct {
LocalISO string
UTCISO string
UnixSeconds int64
Location string
TimeZone string
TimeZoneLabel string
UTCOffset string
UTCOffsetSeconds int
Weekday string
Date string
Time string
DayPeriod string
RelativeDate string
SpeechDate string
SpeechTime string
SpeechPrompt string
Comparisons []ZoneTime
}Do not use speech strings as your only source of truth. They are intentionally lossy so they sound natural through TTS.
For logs, audit trails, database payloads, scheduling, and tool inputs, store the
structured snapshot. For LLM system context, use Prompt() when timezone detail
matters. For owner-facing briefing readouts, use PromptForSpeech() or the
SpeechPrompt field.
The package uses Go's standard time library and local zoneinfo. It does not
call a network API.
go test ./...