Why is time.Parse
not using timezone information? It should return different time for different timezones.
Code
package main
import (
"fmt"
"time"
)
func main() {
t, err := time.Parse("2006-01-02 MST", "2018-05-11 IST")
if err != nil {
return
}
t2, err := time.Parse("2006-01-02 MST", "2018-05-11 UTC")
if err != nil {
return
}
fmt.Println(t.Unix())
fmt.Println(t2.Unix())
}
Output:
1525996800
1525996800
Some explanation to the question itself:
These 2 timestamps 2018-05-11 IST
and 2018-05-11 UTC
do not designate the same time instant because IST has a different offset than UTC: India Standard Time (IST) is 5:30 hours ahead of Coordinated Universal Time (UTC).
And Time.Unix()
returns the elapsed seconds up to the time instant, elapsed since the reference time (January 1, 1970 UTC). Which implies the output should be different!
Running your code on the PlayGround indeed gives wrong result (link).
And it is a timezone related issue. If you try to load the IST timezone:
loc, err := time.LoadLocation("IST")
fmt.Println(loc, err)
Output:
UTC cannot find IST in zip file /usr/local/go/lib/time/zoneinfo.zip
And the reason why "IST" is not supported is because it is ambiguous. It could mean India, Ireland, Israel, etc. time zones, which have different zone offsets and rules.
And documentation of time.Parse()
states that
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.
So the time.time
returned by parse.Parse()
will have 0 offset just like the UTC zone, hence it will result in the same "unix time" (Time.Unix()
will return the same value).
But running it locally (with my CET) timezone gives different, correct result:
t, err := time.Parse("2006-01-02 MST", "2018-05-11 CET")
if err != nil {
panic(err)
}
t2, err := time.Parse("2006-01-02 MST", "2018-05-11 UTC")
if err != nil {
panic(err)
}
fmt.Println(t)
fmt.Println(t2)
fmt.Println(t.Unix())
fmt.Println(t2.Unix())
Output:
2018-05-11 01:00:00 +0200 CEST
2018-05-11 00:00:00 +0000 UTC
1525993200
1525996800
Documentation of time.Parse()
has this to say about parsing a time with zone abbreviation:
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 zone abbreviation "UTC" is recognized as UTC regardless of location. 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. This choice means that such a time can be parsed and reformatted with the same layout losslessly, but the exact instant used in the representation will differ by the actual zone offset. To avoid such problems, prefer time layouts that use a numeric zone offset, or use ParseInLocation.
Documentation suggests to parse with a layout with numeric zone offset, like this:
t, err := time.Parse("2006-01-02 -0700", "2018-05-11 +0530")
if err != nil {
panic(err)
}
Then output (try it on the Go Playground):
2018-05-11 00:00:00 +0530 +0530
2018-05-11 00:00:00 +0000 UTC
1525977000
1525996800
Another option is to use time.FixedZone()
to construct IST
yourself, and use time.ParseInLocation()
, passing our manual IST
location:
ist := time.FixedZone("IST", 330*60) // +5:30
t, err := time.ParseInLocation("2006-01-02 MST", "2018-05-11 IST", ist)
Output will be (try it on the Go Playground):
2018-05-11 00:00:00 +0530 IST
2018-05-11 00:00:00 +0000 UTC
1525977000
1525996800
Yet another option is to load Indian IST zone by Kolkata city:
loc, err := time.LoadLocation("Asia/Kolkata")
if err != nil {
panic(err)
}
Which will produce the same output. Try it on the Go Playground.
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