The RFC3339 standard is a popular way to format timestamps on the internet. RFC3339 timestamps:
- Are human readable.
- Represent instants in time. No intervals.
- Are in UTC time or include an UTC offset. No local time.
- Allow for different precision levels, from years to fractions of a second.
- Use the
YYYY-MM-DD
format. No confusion betweenMM-DD-YYYY
orDD-MM-YYYY
formats. - Are string sortable when every timestamps use consistent time zone information and precision.
This makes it a very pragmatic format.
RFC3339 is a tailored version of the broader ISO8601 standard. It’s not entirely a subset, but it’s pretty close.
RFC3339 in Go’s time package
The Go time
package includes two constants that that define appropriate reference layouts for RFC3339 timestamps:
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
If we pass these to the time.Parse
function we can parse RFC3339 formatted timestamps into time.Time
values.
However, not every valid RFC3339 timestamp can be parsed this way:
- Go expects RFC3339 timestamps to always contain the capital
T
character, the standard allows for lower case or a space. - The standard allows for leap seconds, the
time
does not deal with them.
package main
import (
"fmt"
"log"
"time"
)
func main() {
timestamps := []string{
"2023-12-22T16:25:33Z",
"2023-12-22T16:25:33.8Z",
"2023-12-22T16:25:33.85Z",
"2023-12-22T16:25:33.855Z",
"2023-12-22T16:25:33.855873Z",
"2023-12-22T17:25:33+01:00",
"2023-12-22T17:25:33.855+01:00",
"2023-12-22T17:25:33.855873+01:00",
}
for i, ts := range timestamps {
t, err := time.Parse(time.RFC3339, ts)
if err != nil {
log.Fatalf("%d: %v", i, err)
}
fmt.Println(t)
}
}
Get my free newsletter every second week
Used by 500+ developers to boost their Go skills.
"I'll share tips, interesting links and new content. You'll also get a brief guide to time for developers for free."