Handling time is a common task for programmers. In Go, the standard library time provides the necessary capabilities.
This article will introduce some important functions and methods in the time package, hoping to help those who often need to deal with time-related issues in Go.
Handle Time Zones
In programming, we often encounter the issue of an eight-hour time difference. This is caused by differences in time zones. To better handle them, we need to understand several time definition standards.
GMT (Greenwich Mean Time) is based on the Earth’s rotation and revolution to calculate time. It defines noon as the time when the sun passes through the Royal Greenwich Observatory in the suburbs of London, UK. GMT was the former world standard time.
UTC (Coordinated Universal Time) is more precise than GMT, calculated based on atomic clocks. In situations where precision to the second is not required, UTC can be considered equivalent to GMT. UTC is the current world standard time.
From the Prime Meridian at Greenwich, going east is positive, going west is negative. The globe is divided into 24 standard time zones, with neighboring time zones differing by one hour.
 | 
 | 
In mainland China, the standard time used is in the GMT+8 time zone, known as China Standard Time (CST).
 | 
 | 
This is the result under the default time zone, and +0800 CST is indicated in the time.Now() printout.
Suppose we are in the Los Angeles time zone in the United States, what result do we get?
 | 
 | 
As seen, the result at this time is -0700 PDT, which is Pacific Daylight Time. Due to the time zone difference, the results of the two executions differ by 15 hours.
Note that when using Docker containers, the system’s default time zone is UTC time (0 time zone), which is eight hours behind Beijing time as we need, leading to the classic scenario of the eight-hour time difference problem.
Strategies for dealing with time zone issues can be found in detail in the loading logic of the initLocal() function in src/time/zoneinfo_unix.go. For example, you can solve it by specifying the environment variable TZ or modifying the /etc/localtime file.
Because time zone issues are very important, they are discussed in the first part of the article. Let’s now move on to the usage of the time package.
Time Instant time.Time
The core object in the time package is the time.Time struct. Its definition, used to represent a specific moment in time, is as follows:
 | 
 | 
In computer time handling, two types of clocks are mainly involved:
- Wall clock, also known as clock time, represents specific dates and times.
 - Monotonic clocks, which always guarantee that time moves forward without the issue of wall clock rollback, making them suitable for measuring durations.
 
The wall and ext fields are used to record wall clock and monotonic clock times with nanosecond precision. The bits of these fields are associated with specific information such as years, months, days, hours, minutes, and seconds.
The loc field records the time zone location. When loc is nil, it defaults to UTC.
Because time.Time is used to represent time instants with nanosecond precision, it is typically stored and passed as a value in programs, rather than a pointer.
That is, in time variables or struct fields, we should use time.Time rather than *time.Time.
Getting time.Time
We can get the current local time using the Now function:
 | 
 | 
Or, using the Date function, we can get a specified time based on the year, month, day, and other parameters, along with the time zone:
 | 
 | 
Converting Timestamps
In the computer world, UTC time 0 on January 1, 1970, is considered Unix time 0. To convert a time instant into a Unix timestamp, we calculate the number of seconds, microseconds, etc., elapsed from Unix time 0 to the specified instant.
 | 
 | 
Getting Basic Fields
 | 
 | 
Duration time.Duration
time.Duration represents the time elapsed between two time.Time instants. It uses an int64 to represent the count of nanoseconds, allowing for approximately 290 years of representation.
 | 
 | 
In Go, time.Duration is simply a number in nanoseconds. If a duration is equal to 1000000000, it represents 1 second, or 1000 milliseconds, or 1000000 microseconds, or 1000000000 nanoseconds.
For example, the duration between two time instants separated by 1 hour can be calculated as:
 | 
 | 
The time package defines constant values for these durations:
 | 
 | 
Additionally, time.Duration provides methods to get values at various time granularities:
 | 
 | 
Time Calculation
After learning about time instants and durations, let’s see how to perform time calculations.
 | 
 | 
Addadds or subtracts (positivedmeans addition, negativedmeans subtraction) atime.Durationto atime.Time. We can add or subtract durations of specific nanosecond levels to a specific instant in time.
 | 
 | 
Subreturns the duration between two time instants.
 | 
 | 
AddDateadds or subtracts values based on the year, month, and day dimensions to atime.Time.
Of course, calculating based on the current time instant time.Now() is the most common requirement. Therefore, the time package also provides the following convenient time calculation functions:
 | 
 | 
Since is a shortcut for time.Now().Sub(t).
 | 
 | 
Until is a shortcut for t.Sub(time.Now()).
Usage Example
 | 
 | 
Formatting Time
In other languages, a universal time template is typically used to format time. For example, in Python, %Y represents year, %m represents month, %d represents day, and so on.
However, Go is different. It uses a fixed time (it’s important to note that using other times is not allowed) as the layout template, and this fixed time is the birth time of the Go language.
 | 
 | 
Formatting time involves two conversion functions:
 | 
 | 
Parseconverts a time string to atime.Timeobject based on the layout it can correspond to.
 | 
 | 
Formatconverts atime.Timeobject to a time string based on the given layout.
Example
 | 
 | 
In the time package, Go provides some predefined layout template constants that can be directly used.
 | 
 | 
Here’s a table of optional layout parameters:
 | 
 | 
Timezone Conversion
At the beginning of the article, we discussed timezone issues. If in your code, you need to get the result of the same time.Time in different time zones, you can use its In method.
 | 
 | 
It’s straightforward to use. Let’s see an example code:
 | 
 | 
Conclusion
In general, the functions and methods provided by the time package for time processing meet our usage needs.
Interestingly, Go’s time formatting conversion must adopt Go’s birth time. It’s quite self-centered.