Consider the following code:
package main
import (
"time"
"fmt"
)
const (
format = "2006 01 02 15:04 MST"
date = "2018 08 01 12:00 EDT"
)
func main() {
aloc, _ := time.LoadLocation("America/New_York")
eloc, _ := time.LoadLocation("Europe/Berlin")
tn, _ := time.Parse(format, date)
tl, _ := time.ParseInLocation(format, date, aloc)
fmt.Println(tn) // Says +0000 despite EDT being -0400
fmt.Println(tn.In(eloc)) // Expect 18:00, but get 14:00
fmt.Println(tl) // Correctly -0400
fmt.Println(tl.In(eloc)) // Correctly 18:00
}
You can also try it out on Go Playground.
When I run it, I get this result (both on my own system and through the Playground):
2018-08-01 12:00:00 +0000 EDT
2018-08-01 14:00:00 +0200 CEST
2018-08-01 12:00:00 -0400 EDT
2018-08-01 18:00:00 +0200 CEST
I had expected the first and third line to be the same, and the second and fourth to be the same.
It seems to me that Go's time library doesn't parse the "EDT" timezone identifier I've written in the date string, despite it being part of the format.
My own system (Fedora 26) also recognises EST/EDT as a timezone:
$ TZ='America/New_York' date 080112002018
Wed 1 Aug 12:00:00 EDT 2018
Of course, as you can see, I can force the issue by using ParseInLocation()
, but that's only useful if I know the timezone beforehand. Otherwise I need to parse the 'EDT' part of the date string into 'America/New_York' myself.
Or am I missing something?
Quoting from time#Parse:
When parsing a time with a zone abbreviation like
MST
, if the zone abbreviation has a defined offset in the current location, then that offset is used.
The key here is "current location". For me, that is CST
. Using this works as
expected:
package main
import "time"
func main() {
t, e := time.Parse(time.RFC1123, "Wed, 01 Aug 2018 12:00:00 CST")
if e != nil {
panic(e)
}
s := t.String()
println(s == "2018-08-01 13:00:00 -0500 CDT")
}
If the zone abbreviation is unknown, Parse records the time as being in a fabricated location with the given zone abbreviation and a zero offset.
package main
import "time"
func main() {
t, e := time.Parse(time.RFC1123, "Wed, 01 Aug 2018 12:00:00 EDT")
if e != nil {
panic(e)
}
s := t.String()
println(s == "2018-08-01 12:00:00 +0000 EDT")
}
To avoid such problems, prefer time layouts that use a numeric zone offset, or use ParseInLocation.
package main
import "time"
func main() {
{ // example 1
t, e := time.Parse(time.RFC1123Z, "Wed, 01 Aug 2018 12:00:00 -0400")
if e != nil {
panic(e)
}
s := t.String()
println(s == "2018-08-01 12:00:00 -0400 -0400")
}
{ // example 2
ny, e := time.LoadLocation("America/New_York")
if e != nil {
panic(e)
}
t, e := time.ParseInLocation(time.RFC1123, "Wed, 01 Aug 2018 12:00:00 EDT", ny)
if e != nil {
panic(e)
}
s := t.String()
println(s == "2018-08-01 12:00:00 -0400 EDT")
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With