How to Use Golang Time Package
Golang time
package provides functionalities for handling time.
# Create a time.Time Variable
# time.Time for the Current Time
You can use time.Now
to create a time.Time
variable of the current Time.
import "time"
// Write redundantly to show the type
var t time.Time
t = time.Now()
fmt.Print(t) // 2022-01-31 13:45:56 +0000 UTC
2
3
4
5
6
7
# time.Time for a Specific Time
You can use time.Date
to create a time.Time
variable for a specific time.
The second argument comes a time.Month
type variable, and you can also write as time.Month(1)
to cast int
into time.Month
.
var t time.Time
// 2022-01-31 13:45:56.000000 +00:00
year := 2022
month := time.January // Jatuary - December
// month := time.Month(1) // cast int into time.Month
day := 31
hour := 13
min := 45
sec := 56
nanosec := 0
t = time.Date(year, month, day, hour, min, sec, nanosec, time.UTC)
fmt.Print(t) // 2022-01-31 13:45:56 +0000 UTC
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# time.Time for a Specific TimeZone
The default timezone of time.Time
type variables is UTC
, so if you want to specify another timezone, you can use time.LoadLocation
. In the case of Japan, usually Asia/Tokyo
is used.
var t time.Time
// 2022-01-31 13:45:56.000000 +00:00
year := 2022
month := time.January // Jatuary - December
day := 31
hour := 13
min := 45
sec := 56
nanosec := 0
loc, _ := time.LoadLocation("Asia/Tokyo")
t = time.Date(year, month, day, hour, min, sec, nanosec, loc)
fmt.Print(t) // 2022-01-31 13:45:56 +0900 JST
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Create time.Time with UnixTime
time.Unix
can be used to create a time.Time
variable with Unix Timestamp. The second argument is nanoseconds (0 - 999,999,999).
t = time.Unix(1640769840, 0)
fmt.Print(t) // 2021-12-29 18:24:00 +0900 JST
2
The time zone of this variable is the environment's local timezone. In my case, my PC's timezone is JST
because I'm living in Japan.
# get Information from time.Time
# Year, Month, Day, Hours, Minutes, Seconds, Weekday, etc
You can get information like the following:
t := time.Now()
/*
Year(): 2022
Month(): 1 (string: January)
Day(): 3
Hour(): 15
Minute(): 11
Second(): 40
Weekday(): 1 (string: Monday)
*/
fmt.Printf("Year(): %d\n", t.Year() )
fmt.Printf("Month(): %d (.String(): %s)\n", t.Month(), t.Month().String() )
fmt.Printf("Day(): %d\n", t.Day() )
fmt.Printf("Hour(): %d\n", t.Hour() )
fmt.Printf("Minute(): %d\n", t.Minute() )
fmt.Printf("Second(): %d\n", t.Second() )
fmt.Printf("Weekday(): %d (.String(): %s)\n", t.Weekday(), t.Weekday().String() )
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Returned values are basically int
type , but Month()
and Weekday()
respectively return time.Month
and time.Weekday
type. They can be used as if they are int
type , however , when they are casted into string or called String()
method, they are casted into strings of the month or weekday names like "January" or "Sunday".
# Get Multiple Information
As I got it when I read the source code of AddDate
(opens new window), you can get multiple information like this:
year, month, date := t.Date()
hour, min, sec := t.Clock()
nsec := t.Nanosecond()
2
3
# get TimeZone Information
You can use Time.Zone()
to get the name and offset seconds of the timezone.
t := time.Now()
name, offset := t.Zone()
// name=JST offset=32400
fmt.Printf("name=%s offset=%d", name, offset)
2
3
4
5
# Time Culculations
# Add / Subtract Time
You can use Time.Add
to add or subtract time. If you want to add or subtract days, months, or years, you can also use Time.AddDate
.
t = time.Date(2022, time.Month(1), 3, 12, 23, 34,123, time.UTC)
fmt.Print(t,"\n") // 2022-01-03 12:23:34.000000123 +0000 UTC
// add 20 sec
t = t.Add(time.Duration(20) * time.Second)
fmt.Print(t,"\n") // 2022-01-03 12:23:54.000000123 +0000 UTC
2
3
4
5
6
Time.Add
can be also used to subtract time values by using it with negative values. (You may also know Time.Sub
method, but Time.Sub
is not the opposite of Time.Add
. Time.Sub
is used for culculating the distance between two time.Time
variables.)
// sub 30 hours
t = t.Add(time.Duration(-30) * time.Hour)
fmt.Print(t,"\n") // 2022-01-02 06:23:54.000000123 +0000 UTC
2
3
# Add / Subtract Days
As I wrote above, you can also use Time.AddDate
to add or subtract days, months, or years.
t = time.Date(2022, time.Month(1), 3, 0, 0, 0, 0, time.UTC)
t = t.AddDate(1,1,1)
fmt.Print(t,"\n") // 2023-02-04 00:00:00 +0000 UTC
2
3
If you want to subtract days, you should use negative values.
t = time.Date(2022, time.Month(1), 3, 0, 0, 0, 0, time.UTC)
t = t.AddDate(-1,-2,-6)
fmt.Print(t,"\n") // 2020-10-28 00:00:00 +0000 UTC
2
3
# Add / Subtract Months with the last days
Sometimes Time.Add
may return the different time from expected when it is used with the last days of months.
t = time.Date(2022, time.Month(1), 31, 0, 0, 0, 0, time.UTC)
t = t.AddDate(0,1,0)
fmt.Print(t,"\n") // 2022-03-03 00:00:00 +0000 UTC
2
3
Refering the source code of norm (a private method) (opens new window), values outside the expected range seem to be normalized when time.Date instances are created. For example, "1/31 + 1 months" is once culculated to "2/31", and then finally it will be normalized into "3/3".
If you want to add or subtract months with truncating the last day of months, you should create an original function like this:
func main() {
t := time.Date(2022, time.Month(1), 31, 0, 0, 0, 0, time.UTC)
t = addMonth(t, 13)
fmt.Print(t,"\n") // 2023-02-28 00:00:00 +0000 UTC
}
func addMonth(t time.Time, months int) time.Time {
y, m_, d := t.Date()
m := int(m_)
if months > 0 {
m += months
if m > 12 {
y_ := int((m - 1) / 12)
m -= y_ * 12
y += y_
}
} else if months < 0 {
m -= months
if m < 1 {
y_ := int(-m / 12) + 1
m += y_ * 12
y -= y_
}
}
last_d := getLastDay(y, m)
if d > last_d {
d = last_d
}
print(y,"\n",m,"\n", d, "\n")
h, min, sec := t.Clock()
return time.Date(y, time.Month(m), d, h, min, sec, t.Nanosecond(), t.Location())
}
// get the last day of the month
func getLastDay(y int, m int) int {
if m == 4 || m == 6 || m == 9 || m == 11 {
return 30
}
if m == 2 {
if y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) {
return 29
} else {
return 28
}
}
return 31
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# Culculate the Difference Between Two Times
You can use Time.Sub
to culculate the difference between two times. It takes two arguments of time.Time
variables and returns a time.Duration
variable.
t1 := time.Date(2022, time.Month(1), 31, 12, 23, 34, 5678, time.UTC)
t2 := time.Date(2023, time.Month(2), 3, 23, 34, 56, 7890, time.UTC)
var duration time.Duration
duration = t2.Sub(t1)
// int(duration)=31835482000002212
fmt.Printf("int(duration)=%d\n",int(duration))
// string(duration)=8843h11m22.000002212s
fmt.Printf("string(duration)=%s\n",duration.String())
// methods
/*
days: 368
hours: 8843
minutes: 530591
seconds: 31835482
milliseconds: 31835482111
microseconds: 31835482111111
nanoseconds: 31835482111111102
*/
fmt.Print("days: ", int(duration.Hours() / 24), "\n")
fmt.Print("hours: ", int(duration.Hours()), "\n")
fmt.Print("minutes: ", int(duration.Minutes()), "\n")
fmt.Print("seconds: ", int(duration.Seconds()), "\n")
fmt.Print("milliseconds: ", duration.Milliseconds(), "\n")
fmt.Print("microseconds: ", duration.Microseconds(), "\n")
fmt.Print("nanoseconds: ", duration.Nanoseconds(), "\n")
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
When a time.Duration
variables are cast into int
, it will be nanoseconds, and its String()
method returns a formatted string like "8843h11m22.000002212s".
You can extract information by using methods like Hours()
, Minutes()
, Seconds()
, or Nanoseconds()
. (Note that time.Duration
method names are pluralized like Hours()
while time.Time
methods are in singular form like Hour()
)
Nanoseconds()
, Microseconds()
, and Milliseconds()
methods return int64
type variables while Hours()
, Minutes()
, and Seconds()
return float64
type variable, so if you don't need the fractional part, you should convert returned values into int type.
time.Duration
doesn't have any method to culculate days, so you have to devide the returned values of Hours()
by 24 to culculate it.
# Judgement of leap year
Time package doesn't provide a function to determine whether a year is a leap year or not, so you have to prepare your own function to do so.
You can judge whether a year is a leap year by checking the following conditions:
- Leap years are always multiples of 4.
- BUT multiples of 100 are not leap years.
- BUT multiples of 400 are always leap years.
For example:
- 2004, 2008, 2012 are leap years because all of them are multiples of 4.
- 1900, 1800, 1700 are not leap years because they are multiples of 100 and not multiples of 400.
- 2000, 1600, 1200 are leap years because they are multiples of 400.
The conditional statement of this would be like this:
func isLeapYear(t time.Time) bool {
year := t.Year()
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
2
3
4
# Clone a time.Time variable
Like this:
year, month, day := t.Date()
hour, min, sec := t.Clock()
t = time.Date(year, month, day, hour, min, sec, t.Nanosecond(), t.Location())
2
3
You can also do it with 1 line code with AddDate()
. Maybe it's simpler and easy to understand.
t = t.AddDate(0,0,0)