Golang time function - Learn the Basics in Detail


Written By - Marcus
Advertisement

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 “dtime.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.

Advertisement

 

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.

Advertisement

 

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.

Advertisement

 

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:

Advertisement
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: The time.Now().Unix() function returns the UNIX epoch time, which is the number of seconds that have elapsed since 00:00:00 UTC, 1 January, 1970. The Format() function allows you to convert a time variable to another format; in this case, the RFC3339 format.

You will see the time.Sleep() function many times in this book as a naive way of emulating the delay from the execution of a true function. The time.Second constant allows you to use a one-second duration in Go. If you want to define a duration of 10 seconds, you will need to multiply time.Second by 10. Other similar constants include time.Nanosecondtime.Microsecondtime.Millisecondtime.Minute, and time.Hour. So, the smallest amount of time that can be defined with the time package is the nanosecond. Lastly, the time.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 specified Duration to the Time and returns the result.
Sub(time) This method returns a Duration that expresses the difference between the Time on which the method has been called and the Time provided as the argument.
AddDate(y, m, d) This method adds the specified number of years, months, and days to the Time and returns the result.
After(time) This method returns true if the Time on which the method has been called occurs after the Time provided as the argument.
Before(time) This method returns true if the Time on which the method has been called occurs before the Time provided as the argument.
Equal(time) This method returns true if the Time on which the method has been called is equal to the Time provided as the argument.
IsZero() This method returns true if the Time on 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 the Time value, expressed in the specified Location.
Location() This method returns the Location that is associated with the Time, effectively allowing a time to be expressed in a different time zone.
Round(duration) This method rounds the Time to the nearest interval represented by a Duration value.
Truncate(duration) This method rounds the Time down to the nearest interval represented by a Duration value.

In the following code we try to manipulate the time:

Advertisement
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

The Duration type is an alias to the int64 type and is used to represent a specific number of milliseconds. Custom Duration values are composed from constant Duration values defined in the time package

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()

The time package defines two functions that can be used to create Duration values that represent the amount of time between a specific Time and the current Time

  • Since(time) : This function returns a Duration expressing the elapsed time since the specified Time value.
  • Until(time) : This function returns a Duration expressing the elapsed time until the specified Time value.
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 the Until and Since methods 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()

The time.ParseDuration function parses strings to create Duration values. This function returns a Duration and an error, indicating if there were problems parsing the specified string.

Following table describes the Duration 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.
us or μ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.

Advertisement

https://pkg.go.dev/time

 

Categories GO

Didn't find what you were looking for? Perform a quick search across GoLinuxCloud

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can either use the comments section or contact me form.

Thank You for your support!!

Leave a Comment