chrono
provides additional functionality and improved ergonomics to complement the Go standard library's time
package. It is not a replacement for, nor an extension of, the time
package, but for certain use cases for which it was not explicitly designed to support, chrono
can help to simplify and clarify.
chrono
is also designed to look and feel like Go. Many of the ideas and much of the API is inspired by time
, and should therefore feel familiar. That said, capable time and date libraries exist for most mainstream languages, and chrono
has taken inspiration from several besides Go's time
package, including Rust, Java and Python.
Not all features are complete yet. See the roadmap for the current state. If in doubt, create an issue to ask a question or open a feature request.
Often it's necessary to represent civil time, or dates and times without a time zone or time offset component. Usually, this is achieved using the standard library's time.Date
function and setting the time values to 0
. Alternatively, some people use Google's civil
package.
chrono
provides 3 types for dealing with these use cases: LocalDate
(a date without a time), LocalTime
(a time without a date), and LocalDateTime
(a combination of LocalDate
and LocalTime
).
A LocalDate
and a LocalTime
are initialized with numeric values. A LocalDateTime
can either be initialized with numeric values, or by combining a LocalDate
and LocalTime
(as below):
date := chrono.LocalDateOf(2007, chrono.May, 20)
time := chrono.LocalTimeOf(12, 30, 15, 0)
fmt.Println(chrono.OfLocalDateAndTime(date, time))
β
See more LocalDate
examples.
β
See more LocalTime
examples.
β
See more LocalDateTime
examples.
chrono
differs from the time
package because it uses format codes instead of a mnemonic device. The format codes are borrowed from strftime
/strptime
, and therefore maybe familiar from other languages. The full list is documented here, but here's a simple example of formatting a time:
time := chrono.LocalTimeOf(12, 30, 15, 0)
fmt.Println(time.Format("%H:%M:%S"))
And parsing a time:
var time chrono.LocalTime
fmt.Println(time.Parse("%H:%M:%S", "12:30:15"))
There are also predefined layouts, similar to the time
package, but with the addition of layouts compatible with ISO 8601.
The example above assumes that you know how a date time string is formatted, but that's not always the case. For these situations, ParseToLayout
accepts just a string and attempts to parse it, also returning the layout string.
var c chrono.OffsetDateTime
fmt.Println(chrono.ParseToLayout(
"2006-04-09",
chrono.ParseConfig{},
&c,
)) // %Y-%m-%d
To access this function you need to build with -tag parse
.
This API is incomplete and subject to change until a stable release is reached.
When interfacing with systems where the time
package's duration formatting is not understood, ISO 8601 is a commonly-adopted standard.
time
doesn't support ISO 8601 durations notation. A simple one-liner that uses only the seconds component is possible, but this is neither readable nor solves the problem of parsing such strings:
var d time.Duration
fmt.Printf("PT%dS", int(d.Seconds()))
chrono
supports both parsing and formatting of ISO 8601 strings:
period, duration, _ := chrono.ParseDuration("P3Y6M4DT1M5S")
fmt.Println(chrono.FormatDuration(period, duration))
Alternatively, a Period
and Duration
can be initialized with numeric values:
period := chrono.Period{Years: 3, Months: 6, Days: 4}
duration := chrono.DurationOf(1*chrono.Hour + 30*chrono.Minute + 5*chrono.Second)
fmt.Println(chrono.FormatDuration(period, duration))
Intervals as a concept are absent from the time
package. chrono
introduces the Interval
type, which can be used to represent the intervening time between two time points. This can be by reference to a pair of times (start and end), a start time and a duration, a duration and an end time, or just a duration.
Parsing and formatting of intervals using the ISO 8601 notation is supported as follows, including the use of repeating intervals:
interval, _ := chrono.ParseInterval("R5/2007-03-01T13:00:00Z/P1Y2M10DT2H30M")
fmt.Println(interval.String())