ZetCode

Go current time

last modified October 30, 2026

In this article we show how to get and work with the current date and time in Go. The time package provides the time.Time type, which stores an instant together with a location.

time.Now returns the current local time. A Time value can be printed directly, formatted with a layout, split into components, converted to UTC or another location, and compared with other times.

All examples in this article were compiled and run with Go 1.27.0. Examples that read the current clock print different values on every run; the values shown are from the run used to produce this article.

Current time

time.Now returns the current time in the local location. The Format method turns it into text according to a layout.

main.go
package main

import (
    "fmt"
    "time"
)

func main() {

    now := time.Now()

    fmt.Println(now.Format(time.RFC1123))
    fmt.Println(now.Format("2006-01-02 15:04:05"))
}

time.RFC1123 is a predefined layout. The second call uses a custom layout, 2006-01-02 15:04:05, which prints the date in ISO-like form. Both outputs change with every run.

$ go run main.go
Fri, 30 Oct 2026 19:54:06 CET
2026-10-30 19:54:06

Parts of the current time

A Time value exposes its components through methods: Year, Month, Day, Weekday, YearDay, Hour, Minute, Second and Nanosecond.

main.go
package main

import (
    "fmt"
    "time"
)

func main() {

    now := time.Now()

    fmt.Println("Year:", now.Year())
    fmt.Println("Month:", now.Month())
    fmt.Println("Day:", now.Day())
    fmt.Println("Weekday:", now.Weekday())
    fmt.Println("Year day:", now.YearDay())
    fmt.Println("Hour:", now.Hour())
    fmt.Println("Minute:", now.Minute())
    fmt.Println("Second:", now.Second())
    fmt.Println("Nanosecond:", now.Nanosecond())
}

The month and the weekday are printed as names because their types implement fmt.Stringer. The year day counts from 1, so October 30 is day 303 in a non-leap year.

$ go run main.go
Year: 2026
Month: October
Day: 30
Weekday: Friday
Year day: 303
Hour: 19
Minute: 54
Second: 6
Nanosecond: 781297204

UTC and local time

time.Now uses time.Local. The UTC method returns the same instant in the UTC location, and Location reports the location of the value.

main.go
package main

import (
    "fmt"
    "time"
)

func main() {

    now := time.Now()

    fmt.Println("local:", now.Format(time.RFC3339))
    fmt.Println("utc:  ", now.UTC().Format(time.RFC3339))
    fmt.Println("zone: ", now.Location())
}

Both lines describe the same moment; only the offset differs. In the run shown the local zone is one hour ahead of UTC, and now.Location() is Local rather than a named zone.

$ go run main.go
local: 2026-10-30T19:54:06+01:00
utc:   2026-10-30T18:54:06Z
zone:  Local

Unix timestamps

The Unix, UnixMilli and UnixMicro methods return the number of seconds, milliseconds or microseconds since 1970-01-01 00:00:00 UTC.

main.go
package main

import (
    "fmt"
    "time"
)

func main() {

    now := time.Now()

    fmt.Println("unix:      ", now.Unix())
    fmt.Println("unix milli:", now.UnixMilli())
    fmt.Println("unix micro:", now.UnixMicro())
}

Unix timestamps are time-zone independent and convenient for storage and comparison. The millisecond and microsecond values are simply the same instant at a finer resolution.

$ go run main.go
unix:       1793386446
unix milli: 1793386446954
unix micro: 1793386446954279

Formatting with a layout

Go does not use format specifiers such as yyyy-MM-dd. Instead, a layout is a sample time, and the reference instant is Mon Jan 2 15:04:05 MST 2006. The components of the layout decide how the value is rendered.

main.go
package main

import (
    "fmt"
    "time"
)

func main() {

    t := time.Date(2026, time.October, 30, 9, 5, 7, 0, time.UTC)

    fmt.Println(t.Format(time.RFC3339))
    fmt.Println(t.Format("02 Jan 2006"))
    fmt.Println(t.Format("Monday, 2 January 2006"))
    fmt.Println(t.Format("15:04:05"))
    fmt.Println(t.Format("03:04 PM"))
    fmt.Println(t.Format(time.RFC1123))
}

02 is the zero-padded day and 2 the plain day, 15 is the 24-hour clock and 03 the 12-hour clock. Monday and January print full names, and the last line uses the predefined time.RFC1123 layout.

$ go run main.go
2026-10-30T09:05:07Z
30 Oct 2026
Friday, 30 October 2026
09:05:07
09:05 AM
Fri, 30 Oct 2026 09:05:07 UTC

Truncating and rounding

Truncate cuts a time down to a multiple of a duration, and Round rounds it to the nearest multiple. Both operate on the absolute time, not on the wall clock of the location.

main.go
package main

import (
    "fmt"
    "time"
)

func main() {

    t := time.Date(2026, 10, 30, 9, 37, 42, 0, time.UTC)

    fmt.Println(t.Truncate(time.Hour))
    fmt.Println(t.Truncate(15 * time.Minute))
    fmt.Println(t.Round(30 * time.Minute))
}

Truncating to an hour removes the minutes and seconds. Truncating to 15 minutes sets the time to 09:30, and rounding to 30 minutes chooses 09:30 because 09:37 is closer to 09:30 than to 10:00.

$ go run main.go
2026-10-30 09:00:00 +0000 UTC
2026-10-30 09:30:00 +0000 UTC
2026-10-30 09:30:00 +0000 UTC

Adding durations and calendar time

Add moves a time by a duration, while AddDate adds calendar years, months and days. Sub returns the duration between two times.

main.go
package main

import (
    "fmt"
    "time"
)

func main() {

    t := time.Date(2026, 10, 30, 9, 0, 0, 0, time.UTC)

    fmt.Println(t.Add(90 * time.Minute))
    fmt.Println(t.AddDate(0, 1, 0))
    fmt.Println(t.AddDate(1, 0, 0))
    fmt.Println(t.AddDate(0, 0, -1))
    fmt.Println(t.Sub(t.Add(48 * time.Hour)))
}

Ninety minutes after 09:00 is 10:30. Adding one month to October 30 gives November 30, and adding one year gives October 30 of the next year. The negative result at the end shows that the later time is 48 hours ahead.

$ go run main.go
2026-10-30 10:30:00 +0000 UTC
2026-11-30 09:00:00 +0000 UTC
2027-10-30 09:00:00 +0000 UTC
2026-10-29 09:00:00 +0000 UTC
-48h0m0s

Comparing times

Before, After and Equal compare the instants. The == operator compares the whole struct, including the location, so two values that describe the same instant in different locations are not equal with ==.

main.go
package main

import (
    "fmt"
    "time"
)

func main() {

    a := time.Date(2026, 10, 30, 9, 0, 0, 0, time.UTC)
    b := time.Date(2026, 10, 30, 10, 0, 0, 0, time.UTC)
    c := a.In(time.FixedZone("CET", 3600))

    fmt.Println(a.Before(b), a.After(b), a.Equal(b))
    fmt.Println(a.Equal(c))
    fmt.Println(a == c)
}

The first line compares 09:00 with 10:00 UTC. The value c is the same instant as a expressed in a fixed zone one hour ahead, so a.Equal(c) is true while a == c is false.

$ go run main.go
true false false
true
false

Time zones

time.LoadLocation loads a named zone from the system time zone database. The In method converts a time to that location, and Zone returns the zone abbreviation and its offset in seconds.

main.go
package main

import (
    "fmt"
    "log"
    "time"
)

func main() {

    loc, err := time.LoadLocation("Europe/Bratislava")
    if err != nil {
        log.Fatal(err)
    }

    t := time.Date(2026, 10, 30, 12, 0, 0, 0, time.UTC)

    fmt.Println(t.In(loc).Format(time.RFC3339))
    name, offset := t.In(loc).Zone()
    fmt.Println(name, offset)
}

Bratislava is on Central European Time, one hour ahead of UTC in late October. The offset is 3600 seconds. On systems without a time zone database the call returns an error, which the example reports with log.Fatal.

$ go run main.go
2026-10-30T13:00:00+01:00
CET 3600

Measuring elapsed time

The difference between two time.Now calls measures how long an operation took. time.Since is shorthand for time.Now().Sub(start).

main.go
package main

import (
    "fmt"
    "time"
)

func main() {

    start := time.Now()
    time.Sleep(150 * time.Millisecond)
    elapsed := time.Since(start)

    fmt.Println(elapsed.Round(10 * time.Millisecond))
    fmt.Println(elapsed > 100*time.Millisecond)
}

After a 150 millisecond sleep the rounded result is 150ms, and the comparison confirms that more than 100 milliseconds passed. The exact duration depends on scheduling, so the printed value can differ slightly between runs.

$ go run main.go
150ms
true

The monotonic clock

time.Now records a monotonic clock reading in addition to the wall clock. Before, After, Sub and Add use that reading, so elapsed measurements are not affected by adjustments of the system clock.

main.go
package main

import (
    "fmt"
    "time"
)

func main() {

    now := time.Now()
    later := now.Add(time.Second)

    fmt.Println(now.Before(later))
    fmt.Println(later.Sub(now))
}

The later time is one second after the current one, and Sub returns exactly 1s. Formatting a time, as in the earlier sections, drops the monotonic part and shows only the wall clock.

$ go run main.go
true
1s

Source

Go time package - reference

In this article we have shown how to get the current time in Go, read its components, convert between local time and UTC, work with Unix timestamps, format with layouts, truncate and round, add durations and calendar time, compare times and locations, load time zones, measure elapsed time, and use the monotonic clock.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Go tutorials.