Working with Dates & Time
Prerequisites: File I/O
The time package has two central types:
time.Time— an instant, with a location (time zone).time.Duration— an elapsed time, stored as anint64count of nanoseconds. Build durations from constants:90 * time.Second,2*time.Hour + 30*time.Minute.
Go does not use YYYY-MM-DD style patterns for formatting. Instead you write
how one specific reference time would look:
Mon Jan 2 15:04:05 MST 2006
Each part has a fixed value you can remember as 1 2 3 4 5 6 7: month 01,
day 02, hour 03 (or 15 for 24-hour), minute 04, second 05, year
2006, time zone offset -0700. So "2006-01-02" means "year-month-day".
Syntax
now := time.Now()
t := time.Date(2024, time.March, 9, 14, 5, 0, 0, time.UTC)
s := t.Format("2006-01-02 15:04")
p, err := time.Parse("2006-01-02", "2024-12-25")
later := t.Add(90 * time.Minute)
next := t.AddDate(0, 1, 0) // years, months, days
d := later.Sub(t) // time.Duration
elapsed := time.Since(start) // shorthand for time.Now().Sub(start)
Example
package main
import (
"fmt"
"log"
"time"
)
func main() {
// A fixed time keeps the output repeatable; real code often uses time.Now().
t := time.Date(2024, time.March, 9, 14, 5, 0, 0, time.UTC)
fmt.Println(t.Format("2006-01-02"))
fmt.Println(t.Format("02/01/2006 15:04"))
fmt.Println(t.Format("Mon, Jan 2 2006 at 3:04 PM"))
fmt.Println(t.Format(time.RFC3339))
later := t.Add(90 * time.Minute)
fmt.Println(later.Format(time.Kitchen))
nextMonth := t.AddDate(0, 1, 0)
fmt.Println(nextMonth.Format("2006-01-02"), nextMonth.Weekday())
meeting, err := time.Parse("2006-01-02 15:04", "2024-03-12 09:30")
if err != nil {
log.Fatal(err)
}
until := meeting.Sub(t)
fmt.Println(until, until.Hours())
fmt.Println(meeting.After(t), meeting.Equal(t))
d := 2*time.Hour + 30*time.Minute
fmt.Println(d, d.Minutes())
parsed, err := time.ParseDuration("1h15m30s")
if err != nil {
log.Fatal(err)
}
fmt.Println(parsed.Seconds())
minutes := 3
fmt.Println(time.Duration(minutes) * time.Minute)
}
Expected output
2024-03-09
09/03/2024 14:05
Sat, Mar 9 2024 at 2:05 PM
2024-03-09T14:05:00Z
3:35PM
2024-04-09 Tuesday
67h25m0s 67.41666666666667
true false
2h30m0s 150
4530
3m0s
To measure how long something takes, record start := time.Now() and later
print time.Since(start) — that output naturally differs on every run.
Common mistakes
- Writing layouts with letters (
"YYYY-MM-DD") or the wrong reference numbers ("2006-02-01"swaps month and day). Stick to2006-01-02 15:04:05. - Passing a bare number where a duration is expected:
time.Sleep(5)sleeps for 5 nanoseconds. Write5 * time.Second. - Multiplying an
intvariable by a duration without converting it:n * time.Seconddoes not compile whennis anint; usetime.Duration(n) * time.Second. - Comparing times with
==. Twotime.Timevalues for the same instant can differ in location or internal clock data; uset.Equal(u). - Forgetting that
time.Parsewithout zone information returns UTC. Usetime.ParseInLocationfor local times.
Practice
Parse the date 2024-02-28, add one day, and print the result in the format
Feb 29, 2024 followed by its weekday.
Show solution
package main
import (
"fmt"
"log"
"time"
)
func main() {
d, err := time.Parse("2006-01-02", "2024-02-28")
if err != nil {
log.Fatal(err)
}
next := d.AddDate(0, 0, 1)
fmt.Println(next.Format("Jan 2, 2006"), next.Weekday()) // Feb 29, 2024 Thursday
}