Golang Time Package: time.Now, Duration, Parse, and Date Examples

Deepak Prasad
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.

go
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())
}
Output

Save that program as main.go and run it from the module directory:

bash
go run .

On Go 1.27.0 the location line shows Local and the UTC line uses a Z offset:

output
location: Local
UTC: 2026-08-23T10:38:04Z
2026 August 23
16 7 51

Year, 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.

go
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.Millisecond
  • time.Second, time.Minute, time.Hour

Build a span by multiplying:

go
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.

go
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:

go
future := t.Add(30 * time.Minute)
past := t.Add(-30 * time.Minute)

AddDate shifts calendar fields and accepts year, month, and day deltas independently:

go
nextMonth := t.AddDate(0, 1, 0)
nextYear := t.AddDate(1, 0, 0)

Sub returns the duration from one instant to another:

go
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:

go
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:

go
sec := t.Unix()
ms := t.UnixMilli()
micro := t.UnixMicro()
nano := t.UnixNano()

Rebuild an instant from Unix seconds and optional nanosecond remainder:

go
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:

go
utc := t.UTC()
local := t.Local()

In changes the location representation while preserving the instant:

go
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:

go
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:

go
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.


Frequently Asked Questions

1. How do I get the current time in Go?

Call time.Now(). It returns a time.Time in the process local location.

2. How do I get current UTC time?

Call time.Now().UTC() or build a time.Time with time.UTC as the location.

3. What is time.Duration in Go?

Duration is a named int64 counting nanoseconds between instants. Build it from constants like time.Second or from time.ParseDuration strings.

4. How do I add one month to a Go time?

Use t.AddDate(0, 1, 0) for calendar months. Duration arithmetic does not model calendar months.

5. How do I get a Unix timestamp in Go?

Call t.Unix() for seconds since the Unix epoch, or UnixMilli, UnixMicro, or UnixNano for other scales.

6. How do I convert a Go time to another time zone?

Load a location with time.LoadLocation or use time.FixedZone, then call t.In(loc). The instant stays the same; only the displayed zone changes.

7. What is the difference between time.Sub and time.Since?

end.Sub(start) is the duration from start to end. time.Since(t) is shorthand for time.Now().Sub(t).

8. Does time.Duration support days or months?

No calendar units. Use 24*time.Hour for a fixed day-length span, or AddDate on time.Time for calendar steps.
Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise spanning these technologies, he develops robust solutions and implements efficient data processing and management strategies across various projects and platforms.

  • Go (programming language)
  • Python (programming language)
  • Java (programming language)
  • MongoDB
  • Kubernetes