Overview
In this post, we’ll see how to use the time package provided by Golang by default and what to keep in mind when storing and using time data.
Time package
The time
package is a Golang standard library package that provides time-related functions. You can utilize it to perform various time-related tasks such as getting the current time, comparing time, adding and subtracting time, and formatting time.
Getting the current time
Getting the current time in Golang is very simple.
1package main
2
3import (
4 "fmt"
5 "time"
6)
7
8func main() {
9 currentTime := time.Now()
10 fmt.Println("Current time:", currentTime)
11}
Formatting time
The time
package provides the ability to format time in various formats. You can use the Time.Format
method to convert a time to a string of any format.
1package main
2
3import (
4 "fmt"
5 "time"
6)
7
8func main() {
9 currentTime := time.Now()
10 fmt.Println("Default format:", currentTime.Format("2006-01-02 15:04:05"))
11 fmt.Println("RFC1123 format:", currentTime.Format(time.RFC1123))
12}
Time operations
Time addition and subtraction operations are also very simple. You can use the time.Add
method to add or subtract a specific time interval.
1package main
2
3import (
4 "fmt"
5 "time"
6)
7
8func main() {
9 currentTime := time.Now()
10 oneWeekLater := currentTime.Add(7 * 24 * time.Hour)
11 fmt.Println("One week later:", oneWeekLater)
12}
Dealing with timezones
The time covered by Golang’s time
package includes time zone information by default. This makes it easy to calculate and convert time in different time zones. However, it is important to note that if you do not specify a time zone when using the time
package, it will default to the local time zone of the environment where Golang is running.
1package main
2
3import (
4 "fmt"
5 "time"
6)
7
8func main() {
9 // output the current time using the local timezone
10 currentTime := time.Now()
11 fmt.Println("Current time (local timezone):", currentTime)
12
13 // print the current time in UTC
14 utcTime := time.Now().UTC()
15 fmt.Println("Current time (UTC):", utcTime)
16}
Changing the timezone globally in Golang
Golang itself does not directly provide the ability to change the timezone globally while running a program. Instead, you can set the timezone through system or environment variables.
Changing the timezone in Docker
The default timezone for Docker containers is usually set to UTC. To change the timezone within a container, you can use one of the following methods
1RUN apk add --no-cache tzdata \
2 && ln -snf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime \
3 && echo "Asia/Tokyo" > /etc/timezone
JSON strings and the Time package
When Golang unmarshals JSON types to the time.Time
type, the timezone handling depends on the format of the date and time data contained in the JSON string. By default, if the date and time string in JSON conforms to the RFC 3339 standard (for example, 2006-01-02T15:04:05Z07:00
), it can contain timezone information according to this standard.
If no timezone information is specified in the JSON string, Go’s time.Time
type interprets the time as UTC.
1package main
2
3import (
4 "encoding/json"
5 "fmt"
6 "time"
7)
8
9type EventWithTimezone struct {
10 StartTime time.Time `json:"start_time"`
11}
12
13func main() {
14 jsonStringWithTimezone := `{"start_time": "2024-02-13T15:04:05+09:00"}`
15 jsonStringWithoutTimezone := `{"start_time": "2024-02-13T15:04:05"}`
16
17 var eventWithTimezone EventWithTimezone
18 var eventWithoutTimezone EventWithTimezone
19
20 // JSON unmarshal with timezone information
21 if err := json.Unmarshal([]byte(jsonStringWithTimezone), &eventWithTimezone); err != nil {
22 fmt.Println("Unmarshal with timezone failed:", err)
23 return
24 }
25 } fmt.Println("With timezone:", eventWithTimezone.StartTime)
26
27 // Unmarshal JSON without timezone information
28 if err := json.Unmarshal([]byte(jsonStringWithoutTimezone), &eventWithoutTimezone); err != nil {
29 fmt.Println("Unmarshal without timezone failed:", err)
30 return
31 }
32 // Interpreted as UTC by default.
33 fmt.Println("Without timezone (interpreted as UTC):", eventWithoutTimezone.StartTime)
34}
When processing JSON data, you should consider the above behavior to ensure proper timezone handling.
MYSQL time-related types and Golang timezone handling
In MySQL, both the DATETIME
and TIMESTAMP
types are used to store dates and times, but they differ in the way they handle timezones.
DATETIME
: This type stores date and time without timezone information. This means that theDATETIME
type is not affected by the database server’s timezone setting, and you must manage timezones separately in your application.TIMESTAMP
: TheTIMESTAMP
type is stored converted to UTC, and when retrieved, it is converted and returned based on the current MySQL server’s timezone setting. This means that theTIMESTAMP
type takes timezone information into account internally.
For example, if you save 2023-01-01 12:00:00
in the Seoul time zone as DATETIME
and TIMESTAMP
types, the DATETIME
type will be saved as 2023-01-01 12:00:00
as it is, but the TIMESTAMP
type will be converted to UTC and saved as 2023-01-01 03:00:00
in the database because Seoul/Asia has a UTC+9 value.
Data binding
Golang provides functions to map columns to objects in most DB drives, so let’s see how the stored time-related data is bound according to the type.
First of all, DATETIME
does not have a timezone, so the value will be bound as a timezone-less value. In practice, you may need to explicitly create time data for a specific time zone, and if you check, you’ll see that you can create time without a time zone.
1package main
2
3import (
4 "fmt"
5 "time"
6)
7
8func main() {
9 // Generate time without timezone
10 // Example 1: using the time.Date function and nil Location
11 noZoneTime := time.Date(2023, time.January, 1, 0, 0, 0, 0, 0, nil)
12 fmt.Println("Time without timezone Example 1:", noZoneTime)
13}
Secondly, TIMESTAMP
. Unlike DATETIME
, it has a timezone and is affected by the timezone of the Golang server when fetching data. For example, if the server’s timezone is currently set to Seoul, the UTC timezone will be changed to the Seoul timezone and bound to the object.
Summary
In this post, we briefly introduced Golang’s Time package and summarized the timezones that need to be considered when working with time in the client or DB, along with the detailed code. How to manage them is likely to vary from project to project, but nevertheless, consistent timezone handling between the database server and the application client is important for accurate time data.
It’s especially important for applications that target a multinational audience to manage these time zones clearly.