Time, Dates & Durations
The time package handles every time-related need: instants,
durations, parsing, formatting, time zones, timers, and tickers. Two
things make Go's design distinctive: time.Duration is a
typed integer (nanoseconds) and date format strings use a
reference time instead of cryptic codes like
%Y-%m-%d.
Learning objectives
- Get the current time and create specific instants.
- Use
time.Durationfor arithmetic. - Format and parse times using the reference layout.
- Convert between time zones.
- Schedule one-shot timers and recurring tickers.
time.Time
now := time.Now()
fmt.Println(now) // 2026-04-22 11:35:00.123 +0000 UTC
fmt.Println(now.Year(), now.Month(), now.Day())
birthday := time.Date(1990, time.July, 4, 12, 0, 0, 0, time.UTC)
fmt.Println(birthday)
time.Duration
d := 2*time.Hour + 30*time.Minute
fmt.Println(d) // 2h30m0s
fmt.Println(d.Minutes()) // 150
fmt.Println(d.Seconds()) // 9000
Duration is just int64 nanoseconds. The
constants (time.Hour, etc.) are typed for arithmetic:
5 * time.Second, 500 * time.Millisecond.
Layouts, the famous reference time
Instead of %Y-%m-%d, Go uses an example time:
// THE reference time: Mon Jan 2 15:04:05 MST 2006
// Memorize: 01 02 03 04 05 06 07 (month day hour minute second year week)
const layout = "2006-01-02 15:04:05"
fmt.Println(time.Now().Format(layout)) // 2026-04-22 11:35:00
Common predefined layouts:
time.RFC3339 // "2006-01-02T15:04:05Z07:00"
time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST"
time.DateTime // "2006-01-02 15:04:05"
time.DateOnly // "2006-01-02"
time.TimeOnly // "15:04:05"
2006 is the year, not 2007. 15
is 24-hour. 3 is 12-hour without leading zero. Get one
digit wrong and your output is silently wrong. When in doubt, use the
named constants (time.RFC3339 covers most needs).
Parsing & formatting
t, err := time.Parse("2006-01-02", "2025-12-25")
if err != nil { /* handle */ }
fmt.Println(t.Weekday()) // Thursday
// With explicit time zone
loc, _ := time.LoadLocation("America/New_York")
t, _ = time.ParseInLocation("2006-01-02 15:04", "2025-12-25 09:30", loc)
Time arithmetic
now := time.Now()
later := now.Add(48 * time.Hour) // 2 days from now
elapsed := time.Since(start) // shortcut for Now().Sub(start)
fmt.Println(later.Before(now)) // false
fmt.Println(later.Equal(now.Add(48 * time.Hour))) // true
Time zones
tokyo, _ := time.LoadLocation("Asia/Tokyo")
t := time.Now().In(tokyo)
fmt.Println(t) // same instant, displayed in Tokyo time
utc := time.Now().UTC() // shortcut
Timers & tickers
// One-shot delay
<-time.After(2 * time.Second)
fmt.Println("two seconds later")
// Repeated tick
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for t := range ticker.C {
fmt.Println("tick:", t)
// break out via context, channel, etc.
}
Monotonic clocks
Every time.Now() result includes a monotonic component
that's immune to wall-clock adjustments (NTP, manual changes). For
measuring elapsed durations, this is automatic, you'll never see
negative time.Since values from clock skew.
Check your understanding
Practice exercises
Days until New Year
Write a program that prints the number of full days between today and the next January 1st.
Show solution
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
nextYear := time.Date(now.Year()+1, time.January, 1, 0, 0, 0, 0, now.Location())
days := int(time.Until(nextYear).Hours() / 24)
fmt.Printf("%d days until New Year\n", days)
}
Further reading
Time tamed.