Package time is how Go programs work with instants (time.Time), elapsed spans (time.Duration), sleeping, one-shot timers, repeating tickers, and string conversion. Most day-to-day questions boil down to a few clusters: reading the clock with time.Now, building and parsing durations for timeouts and polling, and moving or comparing time.Time values without string hacks.
This hub keeps examples small and points to time format and parse for layout tables, subtract time / duration for Add versus Sub, and ticker for periodic work. For microbenchmarks use the testing package and benchmarking in Go.
Tested on: Go 1.22 on 64-bit Linux; snippets were run with
go runwhile this article was revised.
Quick answer: Now, Duration, and a few core calls
Use time.Now for the current instant, time.Duration and constants like time.Second for intervals, t.Add / t.Add(-d) to shift a time, time.Since for elapsed wall time from a start instant, and time.ParseDuration for config-style duration strings.
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
fmt.Println(now.Format(time.RFC3339))
d := 5*time.Second + 500*time.Millisecond
fmt.Println(d)
pd, _ := time.ParseDuration("10m")
fmt.Println(pd)
start := time.Now()
time.Sleep(50 * time.Millisecond)
fmt.Println(time.Since(start) > 0)
}The first line is your local timestamp; the next lines show a composed duration, a parsed ten-minute duration, and that Since reports a positive span after a short sleep.
What Is the time Package in Go?
The time package gives you wall-clock instants, arithmetic between them, formatting and parsing, and scheduling primitives. Typical uses include HTTP client timeouts, logging timestamps, rate limits, cache expiry, and simple “run every N seconds” loops.
Common time package use cases
Timeouts, logging, scheduling, measuring latency, comparing expiry timestamps, and converting to RFC3339 for JSON APIs.
Important time types and functions
These names cover most programs; the cheat sheet at the end repeats them in one table.
| Name | Role |
|---|---|
time.Time |
A moment with location |
time.Duration |
Elapsed time between instants |
time.Now |
Current local time |
time.Since / time.Until |
Elapsed or remaining duration versus Now |
time.Parse / time.Format |
String conversion with layouts |
time.Sleep |
Block the current goroutine |
time.NewTimer / time.NewTicker |
One-shot or repeating channel timers |
Get Current Time in Go
Use time.Now
time.Now() returns a time.Time in the process’s local location. Format or convert it when you send it over the wire; store UTC in databases when possible.
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Println(t.Location())
fmt.Println(t.Format(time.RFC3339Nano))
}You should see Local (or your zone name) and an RFC3339 string with offset.
Get current UTC time
package main
import (
"fmt"
"time"
)
func main() {
u := time.Now().UTC()
fmt.Println(u.Format(time.RFC3339))
}The offset should read Z for UTC.
Extract year, month, day, hour, minute, and second
package main
import (
"fmt"
"time"
)
func main() {
t := time.Date(2026, time.June, 18, 14, 30, 45, 0, time.UTC)
y, m, d := t.Date()
h, min, s := t.Clock()
fmt.Println(y, m, d, h, min, s)
}That prints the calendar fields and clock fields for the fixed instant.
Understand time.Duration in Go
What is time.Duration?
time.Duration is a named integer type counting nanoseconds. It is not a calendar type: there is no time.Day or time.Month constant. For exactly twenty-four hours of elapsed time use 24 * time.Hour; for calendar steps use AddDate on time.Time (see subtract time / duration).
Common duration constants
time.Nanosecond, time.Microsecond, time.Millisecond, time.Second, time.Minute, and time.Hour are the usual building blocks; multiply by an integer to scale.
Create duration values using seconds, minutes, and hours
package main
import (
"fmt"
"time"
)
func main() {
d := 2*time.Hour + 30*time.Minute
fmt.Println(d)
fmt.Printf("%.2f hours\n", d.Hours())
}The printed duration matches two and a half hours.
Parse duration from string using time.ParseDuration
ParseDuration accepts combinations of ns, us or µs, ms, s, m, and h. It does not parse d, w, months, or years.
package main
import (
"fmt"
"time"
)
func main() {
for _, s := range []string{"300ms", "10s", "5m", "2h", "1h30m", "-10s"} {
d, err := time.ParseDuration(s)
if err != nil {
fmt.Println(s, "->", err)
continue
}
fmt.Println(s, "->", d)
}
}Each valid string maps to a Duration; invalid units would error.
Add and Subtract Time in Go
Add duration to time
Add returns a new time.Time: t.Add(2 * time.Hour) moves the instant forward.
Subtract duration from time
Use a negative duration: t.Add(-30 * time.Minute) moves backward; see subtract time / duration for pitfalls around Sub.
Find difference between two times using Sub
end.Sub(start) is a time.Duration from start to end.
Find elapsed time using time.Since
time.Since(t) is shorthand for time.Now().Sub(t) when measuring from an earlier capture to now.
package main
import (
"fmt"
"time"
)
func main() {
t := time.Date(2026, 6, 18, 12, 0, 0, 0, time.UTC)
fmt.Println(t.Add(2 * time.Hour))
fmt.Println(t.Add(-30 * time.Minute))
start := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
fmt.Println(time.Since(start) > 0)
}The two Add lines show shifted instants; Since is positive for a past start.
Format Time in Go
Go layouts use the reference time Mon Jan 2 15:04:05 MST 2006, not YYYY-MM-DD tokens. Common patterns include 2006-01-02 for dates and time.RFC3339 for timestamps.
package main
import (
"fmt"
"time"
)
func main() {
t := time.Date(2026, 6, 18, 9, 5, 4, 0, time.UTC)
fmt.Println(t.Format("2006-01-02 15:04:05"))
fmt.Println(t.Format(time.RFC3339))
}For deeper layout tables and locale notes, use golang-time-format.
Parse Time from String
Use time.Parse
Parse(layout, value) uses UTC when the layout has no zone component.
Use time.ParseInLocation for local time zones
ParseInLocation is for wall times that belong to a specific zone, such as a log line stamped in IST.
Parse interprets the string in UTC for layouts without a zone. ParseInLocation attaches the given *time.Location. The layout string must match the input shape exactly.
package main
import (
"fmt"
"time"
)
func main() {
layout := "2006-01-02 15:04:05"
t, err := time.Parse(layout, "2026-06-18 14:30:00")
if err != nil {
panic(err)
}
fmt.Println(t.UTC())
t2, err := time.ParseInLocation(layout, "2026-06-18 14:30:00", time.FixedZone("IST", 5*3600+1800))
if err != nil {
panic(err)
}
fmt.Println(t2)
}You get a UTC instant from Parse and a zoned instant from ParseInLocation.
Compare Time Values
Use Before, After, and Equal
Ordering and equality are defined on time.Time values directly.
Compare deadlines and expiration times
time.Until(deadline) pairs well with select on time.After for timeouts; here it only shows a positive window while the deadline is in the future.
Prefer Before, After, and Equal on time.Time instead of comparing formatted strings.
package main
import (
"fmt"
"time"
)
func main() {
t1 := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
t2 := time.Date(2026, 1, 2, 0, 0, 0, 0, time.UTC)
fmt.Println(t1.Before(t2))
fmt.Println(t2.After(t1))
fmt.Println(t1.Equal(t1))
deadline := time.Now().Add(time.Hour)
fmt.Println(time.Now().Before(deadline))
fmt.Println(time.Until(deadline) > 0)
}Before and After print true for the ordered pair; Equal is true for the same instant. The deadline lines show a future deadline is still ahead of Now.
Timer, Ticker, and Sleep Basics
| API | Use when |
|---|---|
time.Sleep(d) |
Simple pause in the current goroutine |
time.After(d) |
One receive on a channel after d (often in select) |
time.NewTimer(d) |
One-shot timer you can Stop or Reset |
time.NewTicker(d) |
Repeating ticks until Stop |
Use Sleep for a straight delay, NewTimer or After for a single future event, and NewTicker for cadence work. Details and leak avoidance for tickers live in golang-ticker.
package main
import (
"fmt"
"time"
)
func main() {
done := make(chan struct{})
go func() {
time.Sleep(150 * time.Millisecond)
close(done)
}()
select {
case <-done:
fmt.Println("finished")
case <-time.After(400 * time.Millisecond):
fmt.Println("timeout")
}
}The goroutine finishes first, so you should see finished.
Common Mistakes with Go Time
Using the wrong date format layout
Layouts must use Go’s reference date pieces such as 2006-01-02, not YYYY-MM-DD as literal letters.
Confusing duration with calendar days or months
Use AddDate for calendar months and years; use Duration for fixed nanosecond spans.
Ignoring time zones
Parsing and printing depend on location. Be explicit with UTC(), ParseInLocation, and stored offsets when data crosses zones.
Comparing formatted strings instead of time.Time
Use Before / After / Equal for ordering.
Forgetting monotonic readings for short spans
Since and Sub can use a monotonic clock when both values allow it, which makes short measurements more reliable than manual wall math. See the Go 1.9 monotonic time note.
Go time cheat sheet
| Goal | Use |
|---|---|
| Current time | time.Now() |
| UTC now | time.Now().UTC() |
| Unix seconds | time.Now().Unix() |
| Build duration | 5 * time.Second |
| Parse duration string | time.ParseDuration("10m") |
| Move time by span | t.Add(d) / t.Add(-d) |
| Span between instants | t2.Sub(t1) |
Elapsed since t |
time.Since(t) |
Time until t |
time.Until(t) |
| Calendar shift | t.AddDate(y, m, d) |
| Format | t.Format(layout) |
| Parse | time.Parse(layout, s) |
| Compare | Before / After / Equal |
| Sleep | time.Sleep(d) |
| One-shot channel delay | time.After / NewTimer |
| Repeating channel | NewTicker |
Which time function should you use?
- Clock read:
Now. - Interval math:
Duration,ParseDuration,Add,Sub,Since,Until. - Text exchange:
Format,Parse(see format guide). - Scheduling:
Sleep,NewTimer,NewTicker(see ticker guide).
Summary
The time package answers golang time and golang time now with time.Now and friends, and golang time duration with time.Duration, constants, and ParseDuration. Shift instants with Add, measure gaps with Sub and Since, compare with Before/After/Equal, and convert strings with Format and Parse using reference layouts. Pick Sleep, NewTimer, or NewTicker based on whether you need a pause, one future event, or a steady tick—and read the linked guides when those topics need full treatment.
References
- Package time
- Monotonic time (Go 1.9)
- Golang time format and parse
- Subtract time / duration
- Golang ticker

