Getting started with Golang time
Time is what we all need, in real life or in our application / software. Generally, time in real life does not need any introduction, however, we have two types of time provided by operating systems, the “wall clock” and “monotonic clock”.
The “Wall clock” type of time is the normal world time that is synchronized to other clocks globally and we have the “Monotonic Clock” which is not. If you want to check time or tell time, the wall clock is what you need and if you want measure time like doing subtractions, then the Monotonic clock is what you need. For the Wall clock, the calendrical calculations always assume a Gregorian calendar, with no leap seconds.
The Go time package have some functions and types that will help you solve time problems at any scale. We will look at some important Golang Time package functions and types with some examples to make you understand how to use Golang Time.
Important Must Know Golang time Functions
Golang time packages main functions, these functions take a duration of
“d” time.Duration as the only argument, we will talk about Duration
on the go time types section, for now just know “time.Duration” is of
type Int64.
We have some main functions, the time.After and time.Tick function
returns a channel of type Time, the time.Sleep will return function
nothing, whereas there are other functions like the time.Now() and
time.Date() etc. let’s look at these functions with some examples.
Golang Time After Function [ time.After ]
func After(d Duration) <-chan Time
“time.After” waits for the duration of time.Duration d passed into
the function then sends the current time on the returned channel.
package main
import (
"fmt"
"time"
)
var c chan int
func handle(int) {
}
func main() {
select {
case m := <-c:
handle(m)
case <-time.After(10 * time.Second):
fmt.Println("timed out")
}
}
Output:
$ go run main.go
timed out
In the above code, we created a handle function and used the Golang
select syntax to spine up two
goroutines,
one with the handle function and the second is using the time.After
function with a duration of ten seconds. Therefore, the output of this
code is “timed out” because it has waited for 10 seconds.
Golang Time Tick Function [ time.Tick ]
func Tick(d Duration) <-chan Time
Tick will return a channel that sends time to the receiver after waiting
for the specified duration. The Golang time.Tick function does not
have a way to shut down so the Ticker cannot be recovered by the garbage
collector; it “leaks”.
Example code: -
package main
import (
"fmt"
"time"
)
func statusUpdate() string { return "" }
func main() {
c := time.Tick(5 * time.Second)
for next := range c {
fmt.Printf("%v %s\n", next, statusUpdate())
}
}
Output:
$ go run main.go
2022-09-20 12:20:05.820449 +0800 CST m=+5.008349401
2022-09-20 12:20:10.8183667 +0800 CST m=+10.006267101
exit status
Note that I stopped the process manually with CTRL+C , because in the
above code, we started a Tick with 5 seconds duration, iterating over
this channel will continue to print out the time every 5 seconds until
it is manually stopped, so you will mostly use the time.Tick when you
don’t care about shutdown and leaks.
Golang Time Sleep Function [ time.Tick ]
func Sleep(d Duration)
This function does not have any return value but will pause the current
goroutine for the specified duration “d”. A negative or zero duration
causes Sleep to return instantly, it will return nothing.
Example code: -
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("Waiting for 5 seconds before closing main()")
time.Sleep(5 * time.Second)
fmt.Println("Closing main() after waiting for 5 seconds")
}
Output:
$ go run main.go
Waiting for 5 seconds before closing main()
Closing main() after waiting for 5 seconds
In the above code, we waited for five seconds after running the main app before closing it.
Golang Time Date Function [ time.Date() ]
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time
The time.Date function is used to create a time that will match the
inputted arguments using a matching pattern which can found on the
official go pkg website as: -
yyyy-mm-dd hh:mm:ss + nsec nanoseconds
The month, day, hour, min, sec, and nsec values may be outside their usual ranges and will be normalized during the conversion. For example, October 32 converts to November 1.
package main
import (
"fmt"
"time"
)
func main() {
t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
fmt.Printf("Go launched at %s\n", t.Local())
}
Output: -
Go launched at 2009-11-11 07:00:00 +0800 CST
Golang Time Now Function [ time.Now() ]
func Now() Time
This will return the current time.
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Println(t)
}
Output: -
$ go run main.go
2022-09-20 13:40:08.4551392 +0800 CST m=+0.003835401
Assigned t to time.Now() to get the current time then printed it out
to console.
Golang Time Duration Type [ time.Duration ]
type Duration int64
Duration is a nanoseconds counter that is used to represent the time between two instants, its of type int64 as said in the beginning when we started with Golang Time package functions,
Example: -
package main
import (
"fmt"
"time"
)
func expensiveCall() {
time.Sleep(5 * time.Second)
}
func main() {
t0 := time.Now()
expensiveCall()
t1 := time.Now()
fmt.Printf("The call took %v to run.\n", t1.Sub(t0))
}
Output:
$ go run main.go
The call took 5.0009154s to run.
In the above code, we started with a function expensiveCall which has
time.Sleep function to make it sleep for 5 seconds, that is our
duration d of the time.Sleep(5seconds), in the main function, I used
the t0 := time.Now() to start the application so as to get the current
time, then called our function “expensiveCall()” which is said to wait
for 5 seconds based on the duration we passed, the next line also
records the current time into t1 := time.Now() , then we print the
time difference between t0 and t1 with t1.Sub() which will subtract
t0 from t1 and return a duration.
Golang Time Format() - Formatting time output
In this section, you are going to learn how to parse time and date strings in Go, how to convert between different time and date formats, and how to print times and dates in the format you desire
There are three main standards against which we can parse the time:
- RFC3339
- UnixDate
- ANSIC
Here we have a simple code which prints current tame based on all the 3 standards
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Println("RFC3339:", t)
fmt.Println("UnixDate", t)
fmt.Println("ANSIC", t)
}
Output:
$ go run main.go
RFC3339: 2022-09-20 23:35:09.892979205 +0530 IST m=+0.000045328
UnixDate 2022-09-20 23:35:09.892979205 +0530 IST m=+0.000045328
ANSIC 2022-09-20 23:35:09.892979205 +0530 IST m=+0.000045328
So the output format is same for all the 3 standards.
Now coming back to time formatting, we can utilise format() function
by passing the format in which we want to print the time output. Here we
have created a small function which will take the input of date format
and then will convert the current date and time into that format:
package main
import (
"fmt"
"time"
)
func displayDate() {
fmt.Println(time.Now().Date())
}
func main() {
displayDate()
}
Output:
$ go run main.go
2022 September 20
This is a very simple output where we are just formatting
time.Now().Date() output. Let’s do some more examples:
package main
import (
"fmt"
"time"
)
func displayDate(format string) {
fmt.Println(time.Now().Format(format))
}
func main() {
// The output time will vary for you
// but you can check the time format in which we get the output
displayDate("2006-01-02 15:04:05") // The date and time are displayed.
displayDate("15:04:05, 2006-Jan-02 Mon") // The day of the week (Thu) and month (Jul) are displayed.
displayDate("15:04:05, 2006-Jan-02 Monday") // The day of the week is displayed in full.
displayDate("15:04:05, 2006-January-02 MST Mon") // The month is displayed in full; the time zone is also displayed (+08).
displayDate("3:4:05, 2006-1-02 MST Mon") // The time zone (+8) is displayed; a single digit is used for the hour.
displayDate("3:4:05 pm, 2006-1-02 MST Mon") // Morning is displayed as am.
displayDate("3:4:05 PM, 2006-1-02 MST Mon") // Morning is displayed as AM.
}
Output:
$ go run main.go
2022-09-20 23:46:53
23:46:53, 2022-Sep-20 Tue
23:46:53, 2022-Sep-20 Tuesday
23:46:53, 2022-September-20 IST Tue
11:46:53, 2022-9-20 IST Tue
11:46:53 pm, 2022-9-20 IST Tue
11:46:53 PM, 2022-9-20 IST Tue
Golang Time LoadLocation [ time.LoadLocation ]
You can utilize the LoadLocation() function of the time package to
convert your local time to the local time of another time zone. Our
reference time zone will be the Asia/Kolkata time zone. The Format()
function is used to tell Go how we would like to see our output
formatted. The In() function is a reference to a specific time zone we
want our formatting to be present in.
package main
import (
"fmt"
"time"
)
func main() {
// Generate Epoch Time
fmt.Println("Epoch time:", time.Now().Unix())
// Print current time
t := time.Now()
// Print in RFC3339 format
fmt.Println(t, t.Format(time.RFC3339))
// print in weekday day month and year format
fmt.Println(t.Weekday(), t.Day(), t.Month(), t.Year())
// Sleep for 1 second
time.Sleep(time.Second)
// Print current time
t1 := time.Now()
// Print time different
fmt.Println("Time difference:", t1.Sub(t))
// Print time in below format
formatT := t.Format("01 January 2006")
fmt.Println(formatT)
// print time from certain location
loc, _ := time.LoadLocation("Asia/Kolkata")
indTime := t.In(loc)
fmt.Println("Kolkata:", indTime)
}
Output:
$ go run main.go
Epoch time: 1663698144
2022-09-20 23:52:24.562269188 +0530 IST m=+0.000082417 2022-09-20T23:52:24+05:30
Tuesday 20 September 2022
Time difference: 1.000356892s
09 September 2022
Kolkata: 2022-09-20 23:52:24.562269188 +0530 IST
Explanation: Thetime.Now().Unix()function returns theUNIX epoch
time, which is the number of seconds that have elapsed since
00:00:00 UTC, 1 January, 1970. TheFormat()function allows you to
convert atimevariable to another format; in this case,
theRFC3339format.
You will see thetime.Sleep()function many times in this book as a
naive way of emulating the delay from the execution of a true function.
Thetime.Secondconstant allows you to use a one-second duration in
Go. If you want to define a duration of 10 seconds, you will need to
multiplytime.Secondby 10. Other similar constants
includetime.Nanosecond,time.Microsecond,time.Millisecond,time.Minute,
andtime.Hour. So, the smallest amount of time that can be defined
with thetimepackage is the nanosecond. Lastly,
thetime.Sub()function allows you to find the time difference between
two times.
Next we use time.LoadLocation along with In() function to get the
time from the respective timezone. Next we print the time from Kolkata
timezone on the console.
Manipulating Time Values
The time package defines methods for working with Time values, as
described in below table. Some of these methods rely on the Duration
type:
| Name | Description |
|---|---|
| Add(duration) | This method adds the specifiedDurationto theTimeand returns the result. |
| Sub(time) | This method returns aDurationthat expresses the difference between theTimeon which the method has been called and theTimeprovided as the argument. |
| AddDate(y, m, d) | This method adds the specified number of years, months, and days to theTimeand returns the result. |
| After(time) | This method returnstrueif theTimeon which the method has been called occurs after theTimeprovided as the argument. |
| Before(time) | This method returnstrueif theTimeon which the method has been called occurs before theTimeprovided as the argument. |
| Equal(time) | This method returnstrueif theTimeon which the method has been called is equal to theTimeprovided as the argument. |
| IsZero() | This method returnstrueif theTimeon which the method has been called represents the zero-time instant, which is January 1, year 1, 00:00:00 UTC. |
| In(loc) | This method returns theTimevalue, expressed in the specifiedLocation. |
| Location() | This method returns theLocationthat is associated with theTime, effectively allowing a time to be expressed in a different time zone. |
| Round(duration) | This method rounds theTimeto the nearest interval represented by aDurationvalue. |
| Truncate(duration) | This method rounds theTimedown to the nearest interval represented by aDurationvalue. |
In the following code we try to manipulate the time:
package main
import (
"fmt"
"time"
)
func Printfln(template string, values ...interface{}) {
fmt.Printf(template+"\n", values...)
}
func main() {
t, err := time.Parse(time.RFC822, "09 Jun 22 04:35 IST")
if err == nil {
Printfln("After: %v", t.After(time.Now()))
Printfln("Round: %v", t.Round(time.Hour))
Printfln("Truncate: %v", t.Truncate(time.Hour))
} else {
fmt.Println(err.Error())
}
}
Output:
$ go run main.go
After: false
Round: 2022-06-09 04:30:00 +0530 IST
Truncate: 2022-06-09 04:30:00 +0530 IST
TheDurationtype is an alias to theint64type and is used to
represent a specific number of milliseconds. CustomDurationvalues are
composed from constantDurationvalues defined in thetimepackage
package main
import (
"fmt"
"time"
)
func Printfln(template string, values ...interface{}) {
fmt.Printf(template+"\n", values...)
}
func main() {
var d time.Duration = time.Hour + (30 * time.Minute)
Printfln("Hours: %v", d.Hours())
Printfln("Mins: %v", d.Minutes())
Printfln("Seconds: %v", d.Seconds())
Printfln("Millseconds: %v", d.Milliseconds())
rounded := d.Round(time.Hour)
Printfln("Rounded Hours: %v", rounded.Hours())
Printfln("Rounded Mins: %v", rounded.Minutes())
trunc := d.Truncate(time.Hour)
Printfln("Truncated Hours: %v", trunc.Hours())
Printfln("Rounded Mins: %v", trunc.Minutes())
}
Explanation:
The Duration is set to 90 minutes, and then the Hours, Minutes, Seconds, and Milliseconds methods are used to produce output. The Round and Truncate methods are used to create new Duration values, which are written out as hours and minutes.
Output:
$ go run main.go
Hours: 1.5
Mins: 90
Seconds: 5400
Millseconds: 5400000
Rounded Hours: 2
Rounded Mins: 120
Truncated Hours: 1
Rounded Mins: 60
Golang time.Since() and time.Until()
Thetimepackage defines two functions that can be used to
createDurationvalues that represent the amount of time between a
specificTimeand the currentTime
Since(time): This function returns aDurationexpressing the elapsed time since the specifiedTimevalue.Until(time): This function returns aDurationexpressing the elapsed time until the specifiedTimevalue.
package main
import (
"fmt"
"time"
)
func Printfln(template string, values ...interface{}) {
fmt.Printf(template+"\n", values...)
}
func main() {
toYears := func(d time.Duration) int {
return int(d.Hours() / (24 * 365))
}
future := time.Date(2051, 0, 0, 0, 0, 0, 0, time.Local)
past := time.Date(1965, 0, 0, 0, 0, 0, 0, time.Local)
Printfln("Future: %v", toYears(time.Until(future)))
Printfln("Past: %v", toYears(time.Since(past)))
}
The example uses theUntilandSincemethods to work out how many years until 2051 and how many years have passed since 1965.
$ go run main.go
Future: 28
Past: 57
Golang time.ParseDuration()
Thetime.ParseDurationfunction parses strings to
createDurationvalues. This function returns aDurationand anerror,
indicating if there were problems parsing the specified string.
Following table describes theDuration String Unit Indicators
| Unit | Description |
|---|---|
| h | This unit denotes hours. |
| m | This unit denotes minutes. |
| s | This unit denotes seconds. |
| ms | This unit denotes milliseconds. |
| usorμs | These units denotes microseconds. |
| ns | This unit denotes nanoseconds. |
No spaces are allowed between values, which can be specified as integer or floating-point amounts.
package main
import (
"fmt"
"time"
)
func Printfln(template string, values ...interface{}) {
fmt.Printf(template+"\n", values...)
}
func main() {
d, err := time.ParseDuration("1h30m")
if err == nil {
Printfln("Hours: %v", d.Hours())
Printfln("Mins: %v", d.Minutes())
Printfln("Seconds: %v", d.Seconds())
Printfln("Millseconds: %v", d.Milliseconds())
} else {
fmt.Println(err.Error())
}
}
The string specifies 1 hour and 30 minutes.
$ go run main.go
Hours: 1.5
Mins: 90
Seconds: 5400
Millseconds: 5400000
Summary
We have learned that Golang time package supports the wall clock time
and the monotonic time. Golang have some types and functions that works
with channel as well as just work within a channel, like the
time.After and the time.Tick, also the time.Now that’s returns the
current time and the time.Date that is used to create time. we have
talked about time.Duration and how you need it to use the most of the
time functions in Golang.
Reference
More information on these functions and types we were unable to talked about can be found in the Golang time package official documentation.


