This tutorial will teach you how to work with Time in Go (Golang) - including how to parse and format date-time strings, add and subtract time durations, get the current system time, and handle time zones effectively.
The main library we’ll use when working with times and dates is the time standard library.
Getting the Current System Time
Let’s begin by creating a new Time
instance from the current system time:
package main
import (
"fmt"
"time"
)
func main() {
now := time.Now()
fmt.Println(now.String()) // Output: 2009-11-10 23:00:00 +0000 UTC m=+0.000000001
}
After importing the time
standard library, we call the time.Now()
function, which returns the current system time.
Calling the String()
method returns the time as a formatted string.
We can also return the time string in a custom format.
Formatting Time to a String
We can use the Format
method of any Time
instance to return a string in our custom format.
For example:
now := time.Now()
fmt.Println(now.Format("2 Jan 06 03:04PM")) // Output: 10 Nov 09 11:00PM
The date and time in the argument of the Format
method must be the same as the Layout constant, which is defined as:
01/02 03:04:05PM '06 -0700
Note:
01/02
refers to the American convention of MM/DD, which would be the 2nd of January.'06
refers to the year 2006, and-0700
refers to the timezone.
The time library uses this as a reference to map different components of a string to the time that it’s referring to.
We can also use some of the formats defined in the constants to conveniently format our string into recognized standard formats.
For example, we can use the time.UnixDate
layout format to return a Unix-formatted date string:
now := time.Now()
fmt.Println(now.Format(time.UnixDate)) // Output: Tue Nov 10 23:00:00 UTC 2009
Try it yourself by running this code in the Go Playground.
Parsing Time Strings
The time.Parse
function takes a string as input and returns a Time
instance. The time library uses the same layout mechanism from the previous section to convert a string into a Time
instance.
Here’s how to parse a custom-formatted string:
myTime, err := time.Parse("2 Jan 06 03:04PM", "10 Nov 09 11:00PM")
if err != nil {
panic(err)
}
fmt.Println(myTime)
Try it yourself by running this code in the Go Playground.
This is essentially the inverse of the Format
method.
Duration - Adding and Subtracting Time
Go uses the Duration
type to represent the difference between two instances of time.
myTime, err := time.Parse("2 Jan 06 03:04PM", "10 Nov 09 11:00PM")
if err != nil {
panic(err)
}
now := time.Now()
difference := myTime.Sub(now)
fmt.Println(difference) // Output: 8760h0m0s
Try it yourself by running this code in the Go Playground.
The difference
variable is of type Duration
and represents an elapsed duration of time.
Note: If the first time instance is before the second, the duration will be negative.
We can convert this duration into different units like hours or milliseconds:
fmt.Println(difference.Hours()) // Output: 8760
fmt.Println(difference.Milliseconds()) // Output: 31536000000
Note: The largest representable duration is approximately 290 years. To represent durations larger than that, you’ll need to use a custom type.
We can also add a duration to an existing time using the Add
method:
now := time.Now()
later := now.Add(3 * time.Hour)
fmt.Println("now: ", now, "\nlater: ", later)
Output (try it yourself):
now: 2009-11-10 23:00:00 +0000 UTC m=+0.000000001
later: 2009-11-11 02:00:00 +0000 UTC m=+10800.000000001
For readability, use duration constants like time.Hour
, time.Minute
, time.Second
, and time.Millisecond
:
3 * time.Hour // 3 hours
16 * time.Minute // 16 minutes
120 * time.Second // 120 seconds
Time Comparison
To compare time instances, use the Before
, After
, and Equal
methods:
myTime, err := time.Parse("2 Jan 06 03:04PM", "11 Nov 09 11:00PM")
if err != nil {
panic(err)
}
now := time.Now()
fmt.Println(now.Before(myTime)) // Output: true
fmt.Println(now.After(myTime)) // Output: false
fmt.Println(now.Equal(myTime)) // Output: false
Try it yourself by running this code in the Go Playground.
Equal
checks for equality in both value and location, making it more robust than simply comparing timestamps.
Getting Unix/Epoch Time
Unix or Epoch time represents the number of seconds elapsed since January 1, 1970 UTC.
Get the epoch time using the Unix
and UnixMilli
methods:
now := time.Now()
fmt.Println(now.Unix()) // Output: 1257894000
fmt.Println(now.UnixMilli()) // Output: 1257894000000
Working with Time Zones
You’ll be surprised how many bugs can be traced back to incorrect time zone handling. Proper time zone management is crucial for accurate time calculations.
Use time.LoadLocation
to get a specific time zone and time.In
to assign it to a Time
instance.
loc, err := time.LoadLocation("America/New_York")
if err != nil {
panic(err)
}
now := time.Now().In(loc)
fmt.Println("Current time in New York:", now) // Output: Current time in New York: 2009-11-10 18:00:00 -0500 EST
Try it yourself by running this code in the Go Playground.
Convert a time to UTC using the UTC()
method:
utcTime := now.UTC()
fmt.Println(utcTime)
Avoid using
time.Local
unless you’re certain you need the system’s local time zone.
Using time.Ticker
and time.Timer
time.Ticker
allows you to execute code at regular intervals:
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop() // Ensure clean-up
for {
<-ticker.C
// Code to execute every 5 seconds
}
time.Timer
is used for one-off events after a specific duration:
timer := time.NewTimer(10 * time.Second)
defer timer.Stop()
<-timer.C
// Code to execute after 10 seconds
The Time/tzdata
Package
The time/tzdata
package, introduced in Go 1.15, provides access to the IANA Time Zone Database. Ensure this package is available in your application for accurate time zone information.
Best Practices and Further Reading
This post covered essential concepts for working with time and dates in Go. Some tips to avoid common pitfalls:
- Explicitly Manage Time Zones: Always be aware of and explicitly handle time zones to avoid subtle bugs.
- Use Duration Constants: Utilize duration constants (
time.Hour
,time.Minute
, etc.) for better code clarity.
For a deeper dive, consult the official time package documentation.