| Tested on | RHEL 10.2 with Go 1.27.0 |
|---|---|
| Package | time (Go 1.27.0 standard library) |
| Applies to | Any host with Go installed |
| Privilege | Normal user |
| Scope | Overview of time.Now, time.Date, Duration, Add and Sub, Unix timestamps, UTC and time zones, brief Format and Parse, and Sleep, Timer, and Ticker basics. Does not cover layout reference tables, ticker internals, or detailed DST behavior. |
| Related guides | Golang time format Golang subtract time and duration Golang ticker Get current time in milliseconds Getting started with Go |
Package time is how Go programs represent instants (time.Time), elapsed spans (time.Duration), sleeping, timers, tickers, and string conversion. The two central types work together: a time.Time names one moment on the timeline, and a time.Duration names how far apart two moments are in nanoseconds.
Most day-to-day work clusters around reading the clock with time.Now, building or parsing instants for APIs and databases, shifting deadlines with Add or AddDate, and measuring latency with Sub or Since. String conversion and scheduling primitives sit on top of those basics.
This hub keeps examples small and points to Golang time format for layout tables, Golang subtract time and duration for Add versus Sub pitfalls, and Golang ticker for periodic work. For microbenchmarks use the testing package and benchmarking in Go.
Search queries such as golang time or golang time now usually mean either reading the current clock, parsing a timestamp string, or measuring how long something took. The table below maps those tasks to the usual API entry points. Detailed layout rules, ticker lifecycle, and subtraction edge cases stay on the linked guides so this page stays a hub rather than a package encyclopedia.
| Task | API |
|---|---|
| Current time | time.Now() |
| UTC | time.Now().UTC() |
| Build date/time | time.Date() |
| Interval | time.Duration |
| Add interval | t.Add(d) |
| Calendar change | t.AddDate(...) |
| Difference | t2.Sub(t1) |
| Elapsed | time.Since(start) |
| Parse duration | time.ParseDuration() |
| Unix timestamp | t.Unix() |
| Format | t.Format() |
| Parse timestamp | time.Parse() |
Get the current date and time
time.Now() returns the current instant in the process local location. That is the wall clock your operating system exposes to the process, which is why two laptops in different zones can print different RFC3339 strings for the same global instant. Convert or format before you send timestamps over the wire, and store UTC in databases when you need a stable comparison key.
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
fmt.Println("location:", now.Location())
fmt.Println("UTC:", now.UTC().Format(time.RFC3339))
fmt.Println(now.Year(), now.Month(), now.Day())
fmt.Println(now.Hour(), now.Minute(), now.Second())
}Save that program as main.go and run it from the module directory:
go run .On Go 1.27.0 the location line shows Local and the UTC line uses a Z offset:
location: Local
UTC: 2026-08-23T10:38:04Z
2026 August 23
16 7 51Year, Month, Day, Hour, Minute, and Second read calendar and clock fields from the time.Time value. Month() returns a time.Month constant such as time.August, not a plain integer. For a fixed instant you can also call Date() and Clock() to split calendar and clock fields in one step.
time.Now().UTC() is the usual shortcut when JSON APIs or audit logs expect UTC. You do not need a separate API for UTC components: call UTC() once, then read Hour() or Format on the returned value.
Create a time.Time with time.Date
time.Date builds an instant from calendar fields plus a location. A time.Time always represents one moment with an associated zone, not a free-floating date string you can reinterpret later without conversion.
t := time.Date(
2026, time.August, 23,
10, 30, 0, 0,
time.UTC,
)
fmt.Println(t.Format(time.RFC3339))The month argument type is time.Month. Prefer named constants such as time.August for readability. The location argument matters: the same wall-clock fields in time.UTC and time.Local can describe different instants when the zones disagree.
On Go 1.27.0 that program prints 2026-08-23T10:30:00Z. Use time.Date when you know the calendar components from business rules or test fixtures. Use time.Parse when the input is already text. For recurring schedules built from wall times, combine Date with AddDate rather than trying to encode months as fixed Duration values.
Work with time.Duration
time.Duration is a named int64 counting nanoseconds between instants. It is not a calendar type: there is no time.Month or time.Day duration constant, and multiplying time.Hour does not model daylight-saving jumps or variable month lengths.
Common unit constants:
time.Nanosecond,time.Microsecond,time.Millisecondtime.Second,time.Minute,time.Hour
Build a span by multiplying:
d := 5*time.Second + 500*time.Millisecond
fmt.Println(d)That composition prints 5.5s on Go 1.27.0. Duration also exposes Hours, Minutes, and Seconds helpers that return floating-point counts for logging, though the underlying value remains an integer nanosecond count.
Parse duration
time.ParseDuration reads config-style strings such as 300ms, 10s, 5m, 2h, and combinations like 1h30m. It does not parse days, weeks, months, or years. Negative strings such as -10s are valid and produce a negative Duration.
pd, err := time.ParseDuration("1h30m")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(pd)A successful parse of "1h30m" yields 1h30m0s. Always check err when the string comes from a file or environment variable.
For calendar arithmetic use AddDate on time.Time rather than inventing 30 * 24 * time.Hour for a month. Calendar months and years are not fixed nanosecond spans. When you need a timeout or poll interval, Duration is the right tool; when you need "next billing date", AddDate is.
Add, subtract, and compare times
Add shifts an instant by a Duration. A negative duration moves backward, which is the usual way to subtract a fixed span without a separate Sub on time.Time:
future := t.Add(30 * time.Minute)
past := t.Add(-30 * time.Minute)AddDate shifts calendar fields and accepts year, month, and day deltas independently:
nextMonth := t.AddDate(0, 1, 0)
nextYear := t.AddDate(1, 0, 0)Sub returns the duration from one instant to another:
d := end.Sub(start)time.Since(start) is shorthand for time.Now().Sub(start) when measuring elapsed time from a captured start instant. time.Until(deadline) is the mirror image: it reports how long remains until a future time.Time relative to Now.
Compare instants with Before, After, and Equal instead of formatting strings:
t1.Before(t2)
t2.After(t1)
t1.Equal(t1)On Go 1.27.0, adding thirty minutes to 2026-08-23T10:30:00Z yields 2026-08-23T11:00:00Z, and AddDate(0, 1, 0) yields 2026-09-23T10:30:00Z. A twenty-four-hour Add on a day that crosses a DST boundary can differ from AddDate(0, 0, 1) in zones that observe daylight saving.
For subtraction pitfalls around zero results, negative spans, and mixing Duration with calendar math, read Golang subtract time and duration.
Monotonic time
Times returned by time.Now can contain a monotonic clock reading. Go uses that reading for Sub and Since when both operands allow it, which makes short elapsed-time measurements more robust against wall-clock adjustments such as NTP corrections. You do not need to manage the monotonic reading yourself for everyday timing. The monotonic reading is process-local and is not included in formatted, serialized, or Unix timestamp representations. Methods such as UTC, Local, and In, and constructors such as Date, Parse, and Unix, return times without it.
Unix timestamps
Unix timestamps represent an instant as a count from the epoch, independent of display time zone. That makes them a common interchange format between Go services, databases, and JavaScript clients.
Read seconds and finer scales from a time.Time:
sec := t.Unix()
ms := t.UnixMilli()
micro := t.UnixMicro()
nano := t.UnixNano()Rebuild an instant from Unix seconds and optional nanosecond remainder:
rebuilt := time.Unix(sec, 0)On Go 1.27.0, time.Date(2026, time.August, 23, 10, 30, 0, 0, time.UTC) has Unix() 1787481000, and time.Unix(1787481000, 0).UTC() formats back to 2026-08-23T10:30:00Z. Pick the scale your API expects: seconds for classic Unix time, milliseconds for many JSON logs, nanoseconds when you need sub-microsecond precision in metrics.
For millisecond clocks in logs and APIs, see get current time in milliseconds.
Work with UTC and time zones
UTC() and Local() return the same instant represented in UTC or the system local location:
utc := t.UTC()
local := t.Local()In changes the location representation while preserving the instant:
loc, err := time.LoadLocation("Asia/Kolkata")
if err != nil {
return err
}
ist := t.In(loc)2026-08-23T10:30:00Z in Asia/Kolkata displays as 2026-08-23T16:00:00+05:30 on Go 1.27.0. Local follows the system zone and can include DST or offset transitions; UTC is fixed at zero offset.
LoadLocation resolves IANA zone names such as Asia/Kolkata from ZONEINFO when set, the system zoneinfo database, Go's $GOROOT/lib/time/zoneinfo.zip, or an embedded time/tzdata database when that package is imported. For fixed offsets without DST rules, time.FixedZone builds a lightweight Location from a name and offset in seconds.
Be explicit with UTC, LoadLocation, or FixedZone when data crosses zones. Parsing and printing depend on location, not only on the layout string. A timestamp that looks "wrong" after Parse often means the zone was interpreted as UTC when the text was actually local wall time; Golang time format covers ParseInLocation for that case.
Format and parse time strings
Go layouts use the reference time Mon Jan 2 15:04:05 MST 2006, not YYYY-MM-DD tokens. The digits in a layout describe how the reference date would be formatted, which is why 2006-01-02 means a four-digit year and zero-padded month and day.
For everyday API timestamps, named layouts are enough:
text := t.Format(time.RFC3339)
parsed, err := time.Parse(time.RFC3339, text)Format renders a time.Time as text. Parse reconstructs an instant when you know the layout and the string shape match exactly. When the parsed text contains no time-zone information, time.Parse interprets it as UTC. Use ParseInLocation when zone-less input represents local wall time.
Detailed reference-date layouts, ParseInLocation, offset handling, and common formatting mistakes belong in Golang time format. This hub does not duplicate that layout table.
Sleep, Timer, and Ticker basics
| Need | API |
|---|---|
| Pause current goroutine | time.Sleep |
| One future event | time.NewTimer or time.After |
| Repeating ticks | time.Tick(d) or time.NewTicker(d) |
Use Sleep for a straight delay in the current goroutine. It blocks only the calling goroutine, not the whole process, which is why servers still handle other requests while one handler sleeps.
Use NewTimer or After for a single future signal, often inside select. After returns a channel that receives once after the duration; NewTimer returns a *Timer you can Stop or Reset when you need to cancel the wait.
For repeating ticks, time.Tick(d) is the simplest receive-only channel when you only need periodic signals. Use time.NewTicker(d) when you need explicit Stop or Reset control. Since Go 1.23, unreferenced tickers can be recovered by the garbage collector, so Stop is for ceasing ticks, not merely making a ticker collectible.
One select pattern with After is enough here:
select {
case <-done:
fmt.Println("finished")
case <-time.After(400 * time.Millisecond):
fmt.Println("timeout")
}When the done channel closes first, the program prints finished. Timer and ticker lifecycle, Reset semantics, and Tick versus NewTicker trade-offs live in Golang ticker. For repeating work at intervals without building your own loop, see do repetitive tasks at intervals in Go.
Common Go time mistakes
| Mistake | Correct approach |
|---|---|
Using YYYY-MM-DD in layouts |
Go layouts use the reference date 2006-01-02 |
Treating Duration as calendar months |
Use AddDate |
| Comparing formatted strings | Compare time.Time with Before, After, Equal |
| Ignoring location | Use UTC or an explicit Location |
| Using wall-clock formatting to measure elapsed time | Use Sub or Since |
Assuming 24*time.Hour always means next calendar day |
Calendar and DST rules can differ |
References
Summary
The time package answers broad golang time searches with two central types: time.Time for instants and time.Duration for elapsed spans between them.
Read the clock with time.Now, build fixed instants with time.Date, and shift times with Add and AddDate. Measure gaps with Sub and Since, compare with Before, After, and Equal, and exchange epoch values with Unix and time.Unix.
Keep zones explicit with UTC, LoadLocation, and In. Format and parse strings with reference layouts or RFC3339, then open Golang time format when you need the full layout reference.
Pick Sleep, NewTimer, or After for pauses and one-shot delays; use time.Tick or NewTicker for repeating ticks. For subtraction pitfalls and timer or ticker details, use the dedicated guides linked above rather than treating this page as the full time package manual.

