How to format or parse a time in Golang
I'm going to write about how to format or parse a time in Golang, because the usage of Golang time
package is sometimes a little tricky for me.
# Format a time.Time Variable into a String
# Basic Usage
In other languages like PHP, Python, or SQL, date or time format patterns are usually like Y-m-d
or %Y-%m-%d
, but in Golang, time format argument should be a specific form of 2nd January 2006 15:04:05 MST -07:00
.
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Println(string(t.Format("2006-01-02 15:04:05")),"\n") // 2022-01-05 14:57:24
}
2
3
4
5
6
7
8
9
10
Why 2nd January 2006 15:04:05 MST -07:00
? The answer is in the following line quoted from time/format.go (opens new window).
Layout = "01/02 03:04:05PM '06 -0700" // The reference time, in numerical order.
# Format Parameters
I will write down here what characters can be put in a format parameters. You can find them also by looking at time/format.go (opens new window).
Format | Description | |
---|---|---|
Year | 2006 | A full numeric representation of a year, 4 digits |
06 | A two digit representation of a year | |
Month | 1 | Numeric representation of a month, with leading zeros |
01 | Numeric representation of a month, without leading zeros | |
Jan | A short textual representation of a month, three letters | |
January | A full textual representation of a month | |
Day | 2 | Day of the month without leading zeros |
02 | Day of the month, 2 digits with leading zeros | |
_2 | Day of the month with leading spaces like " 2" | |
Week | Mon | A textual representation of a day, three letters |
Monday | A full textual representation of the day of the week | |
Hour | 15 | 24-hour format of an hour with leading zeros |
03 | 12-hour format of an hour with leading zeros | |
3 | 12-hour format of an hour without leading zeros | |
PM | "AM" or "PM" | |
pm | "am" or "pm" | |
Minute | 04 | Minutes with leading zeros |
4 | Minutes without leading zeros | |
Second | 05 | Seconds with leading zeros |
5 | Seconds without leading zeros | |
TimeZone | MST | Timezone identifier. Japanese timezone will be "JST" (not "Asia/Tokyo") |
Z0700 | Difference to Greenwich time (GMT) without colon. Japanese timezone would be "+0900", but UTC timezone will be just "Z". | |
Z07:00 | Difference to Greenwich time (GMT) with colon. Japanese timezone would be "+09:00", but UTC timezone will be just "Z". | |
-07:00 | Difference to Greenwich time (GMT) with colon. Japanese timezone would be "+0900" | |
-0700 | Difference to Greenwich time (GMT) without colon. Japanese timezone would be "+09:00" | |
-07 | GMT offset. In the case of Japan, it will be "+09" |
24-hour format of 0 o'clock will be 12AM
, and 12 o'clock will be 12PM
.
(I feel it slight weird but it might be because I'm Japanese. In Japanese language, usually midnight is referred to as 午前0時
which literally means 0AM
, and noon is referred to as 午前12時
or 午後0時
, which respectively means 12AM
or 0PM
. I don't know the situation of other languages)
# Standard Format
Actually some standard formats are defined in time/format.go (opens new window), so I would recommend to use this format to prevent typos.
const (
Layout = "01/02 03:04:05PM '06 -0700" // The reference time, in numerical order.
ANSIC = "Mon Jan _2 15:04:05 2006"
UnixDate = "Mon Jan _2 15:04:05 MST 2006"
RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
RFC822 = "02 Jan 06 15:04 MST"
RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Kitchen = "3:04PM"
// Handy time stamps.
Stamp = "Jan _2 15:04:05"
StampMilli = "Jan _2 15:04:05.000"
StampMicro = "Jan _2 15:04:05.000000"
StampNano = "Jan _2 15:04:05.000000000"
)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
For example, time.RFC3339
may be usable to save or extract data using a database.
t := time.Now()
fmt.Println(string(t.Format(time.RFC3339)),"\n") // 2022-01-05T15:42:15+09:00
2
# Convert a String into time.Time Type
In Golang, you can use time.Parse
method to convert a string into a time.Time variable.
t, err := time.Parse("2006-01-02 15:04:05", "2022-01-05 15:42:15")
if err != nil {
panic(err)
}
fmt.Println(t) // 2022-01-05 15:42:15 +0000 UTC
2
3
4
5
As I wrote in the above, some format constants are defined in the time package, so you can actually use them.
t, err := time.Parse(time.RFC3339, "2022-01-05T15:42:15+09:00")
if err != nil {
panic(err)
}
fmt.Println(t) // 2022-01-05 15:42:15 +0900 JST
2
3
4
5
With using time.Parse
method, make sure that it doesn't work with slight differences between a format string and a parsed string such as unnecessary spaces or letters.
# Golang equivalent of PHP strtotime
I created a library to parse a datetime string on GitHub because time.Parse
is sometimes tricky.
go-timeparser (opens new window)
import "github.com/kaz-yamam0t0/go-timeparser/timeparser"
// tdata, _ := Now()
// tdata, _ := New("2022-01-31 11:22:33.123456789")
// tdata, _ := NewAsUTC("2022-01-31 11:22:33.123456789")
tdata, _ := NewAsUTC("31st Jan 2022 11:22:33.123456789")
//
// If you want to adjust the timezone offset difference from your local env,
// first create a variable with `New()` and then convert it to UTC with `SetUTC()`
//
// tdata, _ := New("2022-01-31 11:22:33.123456789")
// tdata.SetUTC()
fmt.Println(tdata.GetYear()) // 2022
fmt.Println(tdata.GetMonth()) // 1
fmt.Println(tdata.GetDay()) // 31
fmt.Println(tdata.GetHour()) // 11
fmt.Println(tdata.GetMinute()) // 22
fmt.Println(tdata.GetSecond()) // 33
fmt.Println(tdata.GetMillisecond()) // 123
fmt.Println(tdata.GetMicrosecond()) // 123456
fmt.Println(tdata.GetNanosecond()) // 123456789
//
// Format
//
fmt.Println(tdata.String()) // 2022-01-31T11:22:33+00:00
fmt.Println(tdata.Format("l jS \\of F Y h:i:s A")) // Monday 31st of January 2022 06:22:33 PM
//
// Setter methods
//
tdata.SetYear(2022)
tdata.SetMonth(1)
tdata.SetDay(31)
tdata.SetHour(11)
tdata.SetMinute(22)
tdata.SetSecond(33)
//
// Difference
//
tm, _ := NewAsUTC("2020-12-31 11:22:33.123456789")
fmt.Println(tdata.DiffYears(tm)) // 1
fmt.Println(tdata.DiffMonths(tm)) // 13
fmt.Println(tdata.DiffDays(tm)) // 396
fmt.Println(tdata.DiffHours(tm)) // 9504
fmt.Println(tdata.DiffMinutes(tm)) // 570240
fmt.Println(tdata.DiffSeconds(tm)) // 34214400
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