Table of contents
Part of nurago, a collection of independent Go packages for backend services.
import "github.com/tecnickcom/nurago/pkg/timeutil"
Package timeutil provides two JSON-friendly time types. The standard library’s
time.Time marshals as RFC-3339 only, and time.Duration marshals as a raw
nanosecond integer, which mismatch APIs that expect human-readable strings like
“1h30m” or “2023-01-02T15:04:05Z”. DateTime and Duration marshal to and from
such strings, and the datetime format is selected by a type parameter checked at
compile time.
Types
- [DateTime]: a generic type DateTime[T DateTimeType] that wraps
time.Timeand implementsjson.Marshalerandjson.Unmarshalerusing the format string returned by the type parameter T. It also implementsencoding.TextMarshalerandencoding.TextUnmarshaler, so it can be used as a JSON map key and with text-based encoders (YAML, TOML,flag.TextVar). - [DateTimeType]: the single-method interface (Format() string) that type parameters must satisfy.
- Built-in format types implement
DateTimeTypefor every datetime layout in the standard library (TRFC3339,TRFC3339Nano,TRFC822,TRFC822Z,TRFC850,TRFC1123,TRFC1123Z,TUnixDate,TANSIC,TRubyDate,TKitchen,TStamp,TStampMilli,TStampMicro,TStampNano,TLayout,TDateTime,TDateOnly,TTimeOnly), plusTJirafor Jira’s timestamp format. - [Duration]: an alias for
time.Durationthat marshals as a human-readable string (e.g. “1h30m0s”) and unmarshals from both string and numeric JSON values. It also implementsencoding.TextMarshalerandencoding.TextUnmarshalerfor use as a map key and with text-based encoders.
Usage
Typed datetime in a struct:
type Event struct {
StartedAt timeutil.DateTime`timeutil.TRFC3339` `json:"started_at"`
EndedAt timeutil.DateTime`timeutil.TDateOnly` `json:"ended_at"`
}
e := Event{
StartedAt: timeutil.DateTime[timeutil.TRFC3339](time.Now()),
}
b, _ := json.Marshal(e)
// {"started_at":"2023-01-02T15:04:05Z","ended_at":"2023-01-02"}
Human-readable duration in configuration:
type Config struct {
Timeout timeutil.Duration `json:"timeout"`
}
var cfg Config
_ = json.Unmarshal([]byte(`{"timeout":"30s"}`), &cfg)
// cfg.Timeout is equivalent to 30 * time.Second
Custom format:
type TYearMonth struct{}
func (TYearMonth) Format() string { return "2006-01" }
type Report struct {
Month timeutil.DateTime`TYearMonth` `json:"month"`
}
When To Use
- An API expects durations as “1h30m” rather than as nanosecond integers.
- Timestamps must use a format other than RFC 3339, chosen at compile time.
Example
dt := timeutil.DateTime[timeutil.TRFC3339](time.Date(2023, 1, 2, 15, 4, 5, 0, time.UTC))
b, err := json.Marshal(dt)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(b))
// Output: "2023-01-02T15:04:05Z"
Full source is in example_datetime_test.go. More runnable examples are on pkg.go.dev.
Dependencies
This package reaches no external module: it uses only the Go standard library.