Learn Go← Dashboard

fmt, io, os, bufio, encoding/json, net/http, time, slog, regexp, flag, embed.

time and Duration

The time package has two main types: time.Time (an instant) and time.Duration (a length of time, expressed as nanoseconds).

Now and intervals

now := time.Now()
fmt.Println(now)

future := now.Add(2 * time.Hour)
elapsed := time.Since(start)        // shorthand for time.Now().Sub(start)
fmt.Println(elapsed)                // 1.234s

Durations

Constants in the package use natural names:

time.Nanosecond  // 1
time.Microsecond // 1000
time.Millisecond // 1_000_000
time.Second      // 1_000_000_000
time.Minute
time.Hour

So 2*time.Second + 500*time.Millisecond is "2.5 seconds". A Duration is just an int64 — you can compare, add, divide, etc.

go playground
Loading...

Formatting is by example

Go's time format string is the reference time:

Mon Jan 2 15:04:05 MST 2006

You rearrange that template to whatever shape you want. So "2006-01-02" is ISO date, "15:04" is HH:MM, etc.

| Common constant | Example output | | ----------------- | ----------------------------- | | time.RFC3339 | 2006-01-02T15:04:05Z07:00 | | time.Kitchen | 3:04PM | | time.DateOnly | 2006-01-02 | | time.TimeOnly | 15:04:05 |

Tickers and timers

ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for range ticker.C {
    doSomething()
}

ticker.C is a channel — every second a tick arrives. time.After(d) is the one-shot version (returns a channel that delivers once after d).

Monotonic vs wall clock

time.Now() records both a wall-clock time (good for displaying, sensitive to NTP / clock changes) and a monotonic reading (always moves forward, good for measuring durations). Sub and Since use the monotonic part — so they remain correct even if the system clock jumps.

t.Round and most serialization (JSON, DB) strip the monotonic part. So time.Since(t) where t came from JSON falls back to wall-clock arithmetic.

Go's reference time is `Mon Jan 2 15:04:05 MST 2006`. Why those exact values?