Time & Dates

Reviewed & published by Brayan K

The time package represents an instant as a time.Time and a span as a time.Duration, and its distinctive reference-layout (2006-01-02 15:04:05) drives all formatting and parsing.

Part of the free Go course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ Creating & Inspecting a Time

In real code you'd call time.Now(), but for reproducible examples we build a fixed instant with time.Date(year, month, day, hour, min, sec, nsec, loc). From a time.Time you can read every field — Year(), Month(), Day(), Weekday() — and get the Unix timestamp with Unix().

package main

import (
    "fmt"
    "time"
)

func main() {
    // Use a FIXED time so output is deterministic.
    // time.Date(year, month, day, hour, min, sec, nsec, loc).
    t := time.Date(2026, time.June, 18, 14, 30, 0, 0, time.UTC)

    fmt.Println("date:", t.Year(), t.Month(), t.Day())
    fmt.Println("time:", t.Hour(), t.Minute())
    fmt.Println("weekday:", t.Weekday())

    // Unix timestamp (seconds since 1970-01-01 UTC).
    fmt.Println("unix:", t.Unix())
}

2️⃣ Durations & Comparing Times

A time.Duration is a length of time built from constants like time.Hour. Add one with t.Add(...), and subtract two times with later.Sub(t) to get the duration between them (convert with .Hours()). Compare instants with Before, After, and Equal; shift by calendar units (months, years) with AddDate.

package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Date(2026, time.June, 18, 14, 30, 0, 0, time.UTC)

    // Duration arithmetic: Add a duration, Sub two times.
    later := t.Add(48*time.Hour + 30*time.Minute)
    fmt.Println("48h30m later:", later.Format("2006-01-02 15:04"))

    gap := later.Sub(t)
    fmt.Println("gap hours:", gap.Hours()) // 48.5

    // Compare times with Before / After / Equal.
    fmt.Println("t before later?", t.Before(later)) // true
    fmt.Println("equal to self?", t.Equal(t))       // true

    // AddDate adjusts by calendar years/months/days.
    nextYear := t.AddDate(1, 0, 0)
    fmt.Println("next year:", nextYear.Year()) // 2027
}

3️⃣ Formatting & Parsing with the Reference Layout

Go's signature feature: instead of letter codes, you describe a format by writing the reference date Mon Jan 2 15:04:05 MST 2006 the way you want the output to look. 2006 is the year, 01 the month, 02 the day, 15 the 24-hour clock, and so on. The same layout drives time.Parse, which reads a string back into a time.Time.

package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Date(2026, time.June, 18, 14, 30, 45, 0, time.UTC)

    // Go's layout uses the REFERENCE time Mon Jan 2 15:04:05 MST 2006.
    // You spell out HOW you want it using that exact date's pieces.
    fmt.Println(t.Format("2006-01-02"))      // 2026-06-18
    fmt.Println(t.Format("15:04:05"))        // 14:30:45
    fmt.Println(t.Format("Mon Jan 2, 2006")) // Thu Jun 18, 2026
    fmt.Println(t.Format("3:04 PM"))         // 2:30 PM

    // Parse reads a string back into a time using the same layout.
    parsed, err := time.Parse("2006-01-02", "2025-12-25")
    fmt.Println(parsed.Format("Jan 2, 2006"), err)

    // Sub measures the gap between two times as a Duration.
    deadline := t.Add(3 * time.Hour)
    fmt.Println("until deadline:", deadline.Sub(t)) // 3h0m0s
}

🎯 Your Turn

Format the fixed time as 2026-07-04 09:05 using the reference layout. Fill in the blank.

package main

import (
    "fmt"
    "time"
)

func main() {
    t := time.Date(2026, time.July, 4, 9, 5, 0, 0, time.UTC)

    // Format t as "2026-07-04 09:05" using the REFERENCE layout.
    // Remember: year=2006 month=01 day=02 hour=15 minute=04.
    fmt.Println(t.Format("___")) // 👉 2006-01-02 15:04

    // ✅ Expected output:  2026-07-04 09:05
}

Common Errors (and the fix)

🎯 Mini-Challenge: Days Between Dates

Compute the number of days between two fixed dates: subtract to get a Duration, divide its Hours() by 24, and print with one decimal. Also print the end date as "Mon, 02 Jan 2006".

package main

import (
    "fmt"
    "time"
)

func main() {
    // 🎯 MINI-CHALLENGE: how many days between two dates?
    // 1) Sub(end, start) gives a Duration.
    // 2) Divide its Hours() by 24 and print with one decimal: %.1f
    // 3) Also print end formatted as "Mon, 02 Jan 2006".
    //
    // ✅ Expected output:
    // days: 73.5
    // end formatted: Sun, 15 Mar 2026

    start := time.Date(2026, time.January, 1, 0, 0, 0, 0, time.UTC)
    end := time.Date(2026, time.March, 15, 12, 0, 0, 0, time.UTC)
    // your code here
}

🎉 Lesson Complete!

Practice quiz

Which reference layout formats a date as 2026-07-04?

  • YYYY-MM-DD
  • 2020-12-31
  • 2006-01-02
  • 01-02-2006

Answer: 2006-01-02. Go uses the reference time Mon Jan 2 15:04:05 MST 2006 as the layout.

In the reference layout, what does 15 represent?

  • The hour on a 24-hour clock
  • The day of the month
  • The minute
  • The 12-hour hour

Answer: The hour on a 24-hour clock. 15 is the 24-hour clock; 04 is the minute, 05 the second.

Which constructor builds a fixed, deterministic instant?

  • time.Now()
  • time.Fixed(...)
  • time.New(...)
  • time.Date(year, month, day, hour, min, sec, nsec, loc)

Answer: time.Date(year, month, day, hour, min, sec, nsec, loc). time.Now() depends on the wall clock; time.Date gives reproducible output.

How do you get the duration between two times?

  • later - earlier
  • later.Sub(earlier)
  • time.Diff(later, earlier)
  • later.Minus(earlier)

Answer: later.Sub(earlier). Sub returns a time.Duration; later.Sub(t).Hours() converts it to hours.

Which shifts a time by calendar units like one year?

  • t.AddDate(1, 0, 0)
  • t.Add(1 * time.Year)
  • t.AddYear(1)
  • t.Add(365 * time.Hour)

Answer: t.AddDate(1, 0, 0). AddDate respects month lengths and leap years; there is no time.Year constant.

How should you test whether two times are the same instant?

  • a == b
  • a.Same(b)
  • a.Equal(b)
  • a.Compare(b) only

Answer: a.Equal(b). Use Equal; == can differ on monotonic-clock or location data.

What does t.Add(48*time.Hour + 30*time.Minute) add to t?

  • 48 minutes and 30 seconds
  • 48 hours and 30 minutes
  • 78 minutes
  • 48.5 minutes

Answer: 48 hours and 30 minutes. Duration constants combine: that is a 48h30m shift, i.e. 48.5 hours.

What does time.Parse use to read a string into a time.Time?

  • A locale setting
  • Automatic detection
  • A regular expression
  • The same reference layout you format with

Answer: The same reference layout you format with. Parse and Format share the 2006-01-02 style layout.

What does time.Since(t) return?

  • The instant t formatted
  • The elapsed duration since t (time.Now().Sub(t))
  • A boolean for whether t is past
  • The Unix timestamp of t

Answer: The elapsed duration since t (time.Now().Sub(t)). Since(t) is shorthand for time.Now().Sub(t).

What does t.Unix() return?

  • Nanoseconds since midnight
  • The weekday number
  • Seconds since 1970-01-01 UTC
  • Milliseconds since the program started

Answer: Seconds since 1970-01-01 UTC. Unix() is the Unix timestamp in seconds.

Continue this course

Frequently asked questions

Why does Go format dates with 2006-01-02 instead of yyyy-mm-dd?

Go uses a reference time — Mon Jan 2 15:04:05 MST 2006 — as the layout. You write the output you want using the pieces of that specific date: 2006 means the year, 01 the month, 02 the day, 15 the hour (24-hour), 04 the minute, 05 the second. It reads oddly at first, but it's unambiguous and you never have to memorize cryptic letter codes. A mnemonic: the numbers are 1 2 3 4 5 6 (month, day, hour, minute, second, year).

What is a time.Duration and how do I do arithmetic with it?

A time.Duration is a count of nanoseconds with handy constants like time.Hour and time.Minute. You add a duration to a time with t.Add(2 * time.Hour), and subtract two times with later.Sub(earlier) to get the duration between them. Methods like Hours(), Minutes(), and Seconds() convert a duration to a float64 in those units.

What's the difference between Add and AddDate?

Add takes a time.Duration and shifts by an exact amount of clock time, e.g. t.Add(48 * time.Hour). AddDate shifts by calendar units — years, months, and days — with t.AddDate(1, 0, 0) for one year. AddDate respects month lengths and leap years, so it's the right tool for 'one month from now' rather than adding a fixed number of hours.

How do I compare two times?

Use the methods Before, After, and Equal: a.Before(b), a.After(b), a.Equal(b). Avoid comparing time.Time values with == because two times can represent the same instant yet differ in their monotonic-clock reading or location; Equal compares the actual instant and handles those cases correctly.

What does time.Since do, and what about time.Sleep?

time.Since(t) is shorthand for time.Now().Sub(t) — the elapsed duration since t, which is great for timing how long an operation took. time.Sleep(d) pauses the current goroutine for the duration d, e.g. time.Sleep(2 * time.Second). Both deal with real wall-clock time, so their output isn't deterministic, which is why this lesson uses fixed time.Date values for the examples.