Time in Go

time.Now

The time.Now call captures the current instant with nanosecond precision and your local zone attached. From it you can read the calendar fields, or compare two moments with Before, After, and Equal.

package main import ( "fmt" "time" ) func main() { now := time.Now() fmt.Println(now.Year(), int(now.Month()), now.Day()) fmt.Println(now.Weekday()) }

Year, Month, and Day split the instant into calendar parts, while Weekday names the day. Store moments as time.Time values and format them only at the moment of display.

Reference layout 2006-01-02 15:04:05

Go formats time with a reference instant instead of letter codes. Memorize one date: 2006-01-02 15:04:05. Every layout reuses its digits, with 2006 for the year, 01 for the month, 02 for the day, and 15:04:05 for the clock.

package main import ( "fmt" "time" ) func main() { t := time.Date(2026, time.October, 6, 15, 4, 5, 0, time.UTC) fmt.Println(t.Format("2006-01-02 15:04:05")) }

2026-10-06 15:04:05

The layout shows where each digit goes, and Format fills in the real values. Build timestamps for logs and file names from this pattern, and reach for RFC3339 when machines on both ends must agree.

Parse input

Parsing reads a string with the same layout trick in reverse. Give the layout first and the input second, always check the error, and prefer time.Parse when the text carries no zone information.

package main import ( "fmt" "time" ) func main() { d, err := time.Parse("2006-01-02", "2026-10-06") if err != nil { fmt.Println(err) return } fmt.Println(d.Weekday()) }

Tuesday

The layout must mirror the input exactly, down to every dash, or Parse returns an error. When the text names a zone or an offset, ParseInLocation or the RFC3339 layout handles it.

Durations and tickers

Subtracting two instants gives a Duration measured in nanoseconds, with helpers such as Millisecond and Second for scale. Sleep pauses the goroutine, tickers deliver repeated beats through a channel, and After fires once when a deadline passes.

package main import ( "fmt" "time" ) func main() { start := time.Now() time.Sleep(10 * time.Millisecond) fmt.Println(time.Since(start)) tick := time.NewTicker(5 * time.Millisecond) defer tick.Stop() deadline := time.After(22 * time.Millisecond) for { select { case t := <-tick.C: fmt.Println("tick", t.Format("05.000")) case <-deadline: fmt.Println("done") return } } }

Since measures the Sleep above, then the loop prints a few ticks until the deadline channel fires. Always stop tickers you no longer need: each one holds a goroutine until Stop releases it.

Next: JSON

Article author: Arthur Isaev