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, and get the current system time.
The main library that we’ll use when working with times and dates is the time standard library.
Getting the Current System Time
Let’s begin with an example of creating a new Time
instance from the current system time:
package main
import (
"fmt"
"time"
)
func main() {
// `now` is an instance of time.Time
now := time.Now()
fmt.Println(now.String())
}
Output (try it yourself):
2009-11-10 23:00:00 +0000 UTC m=+0.000000001
After importing the time
standard library, we can call the time.Now()
function - which will return 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, if we run:
now := time.Now()
// the time and date in this string is intentional, as we will discuss soon
fmt.Println(now.Format("2 Jan 06 03:04PM"))
We will get the output (try it yourself):
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, that 01/02 refers to the American convention of MM/DD, which would be the 2nd 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 (Try it yourself):
Tue Nov 10 23:00:00 UTC 2009
Parsing Time Strings
The time.Parse
function takes a string as an input and returns a time instance.
This string can be in a number of formats, depending on your code. The time library uses the same layout mechanism that we saw in the previous section to convert a string into a Time
instance.
Let’s see an example where we parse a custom-formatted string using the Parse
function:
// layout input time
myTime, err := time.Parse("2 Jan 06 03:04PM", "10 Nov 10 11:00PM")
// parsing the time may return an error if the layout format doesn't
// match the input time
if err != nil {
panic(err)
}
fmt.Println(myTime)
This is basically the inverse of the Format
method.
Duration - Adding and Subtracting Time
Go uses the Duration
type to show the difference between two instants of time.
myTime, err := time.Parse("2 Jan 06 03:04PM", "10 Nov 10 11:00PM")
if err != nil {
panic(err)
}
now := time.Now()
difference := myTime.Sub(now)
fmt.Println(difference)
Output (try it yourself):
8760h0m0s
Here, the difference
variable is of type Duration
, and as the name suggests, it represents some elapsed duration of time.
Note, that if the first time instance is before the second, the duration will be a negative value
We can convert this duration into different units like hours or milliseconds:
fmt.Println(difference.Hours())
fmt.Println(difference.Milliseconds())
This will give us the integer values of the duration:
8760
31536000000
Note that the largest representable duration is approximately 290 years, so if you need to represent a duration larger than that, you’d be better off using your own 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
Since duration is internally represented as a number, we can multiply duration constants like Minute
, Second
and Millisecond
with integers.
3 * time.Hour // 3 hours
16 * time.Minute // 16 minutes
120 * time.Second // 120 seconds
This is useful for code readability since you know the unit of time just be seeing the constant used.
Time Comparison
If we just want to know if an instant of time is greater than or lesser than another one, we can use the Before
and After
methods, which return a boolean value:
myTime, err := time.Parse("2 Jan 06 03:04PM", "10 Nov 10 11:00PM")
if err != nil {
panic(err)
}
now := time.Now()
fmt.Println(now.Before(myTime))
fmt.Println(now.After(myTime))
Output (try it yourself):
true
false
This is more concise and readable for pure comparison, rather than using Sub
and checking for a positive or negative duration.
Getting Unix/Epoch Time
The Unix or Epoch time is the total number of seconds elapsed since January 1, 1970 UTC. It is a convenient way to represent a timezone-independent instant of time since it is returned as an integer value, which can be stored efficiently in databases and storage systems.
We can use the Unix
and UnixMilli
methods to get the epoch time from a Time
instance:
now := time.Now()
fmt.Println(now.Unix())
fmt.Println(now.UnixMilli())
Output (try it yourself):
1257894000
1257894000000
Conclusion and Further Reading
This post has covered most of the concepts you need to know to get started working with times and dates in Go.
Some key points to remember:
- Most applications take user input in the form of strings. We can use the
Format
andParse
functions to convert between arbitrary strings and nativeTime
representations. - To perform operations on time in Go, it’s always better to use the built in
Add
andSubtract
methods. Similarly, useBefore
andAfter
for time comparison. - For data storage, converting to an integer in the form of epoch seconds or milliseconds is more optimal. This will also allow you to perform arithmetic operations on your time if you need to.
If you want a comprehensive list of all the functions and methods available, check out the library documentation page.