对问题本身的一些解释:
这 2 个时间戳 2018-05-11 IST 和 2018-05-11 UTC 不指定同一时刻,因为 IST 与 UTC 有不同的偏移量:印度标准时间 (IST) 比协调世界时 (UTC) 早 5:30 小时。
并且Time.Unix() 返回自参考时间(UTC 时间 1970 年 1 月 1 日)以来已过去的秒数。这意味着输出应该不同!
在 PlayGround 上运行您的代码确实会给出错误的结果 (link)。
这是一个时区相关的问题。如果您尝试加载 IST 时区:
loc, err := time.LoadLocation("IST")
fmt.Println(loc, err)
输出:
UTC cannot find IST in zip file /usr/local/go/lib/time/zoneinfo.zip
而“IST”之所以不受支持,是因为它不明确。这可能意味着印度、爱尔兰、以色列等时区,它们有不同的时区偏移和规则。
time.Parse() 的文档指出
如果区域缩写未知,Parse 将时间记录为在具有给定区域缩写和零偏移量的虚构位置。
因此,parse.Parse() 返回的 time.time 与 UTC 时区一样具有 0 偏移量,因此它将产生相同的“unix 时间”(Time.Unix() 将返回相同的值)。
但是在本地(使用我的 CET)时区运行它会给出不同的正确结果:
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())
输出:
2018-05-11 01:00:00 +0200 CEST
2018-05-11 00:00:00 +0000 UTC
1525993200
1525996800
time.Parse() 的文档中有关于使用区域缩写解析时间的说法:
当使用像 MST 这样的区域缩写解析时间时,如果区域缩写在当前位置有定义的偏移量,则使用该偏移量。时区缩写“UTC”被识别为 UTC,与位置无关。如果区域缩写未知,Parse 将时间记录为在具有给定区域缩写和零偏移的虚构位置。这种选择意味着可以使用相同的布局无损地解析和重新格式化这样的时间,但表示中使用的确切时刻将因实际区域偏移量而异。为避免此类问题,请首选使用数字区域偏移的时间布局,或使用 ParseInLocation。
文档建议使用带有数字区域偏移的布局进行解析,如下所示:
t, err := time.Parse("2006-01-02 -0700", "2018-05-11 +0530")
if err != nil {
panic(err)
}
然后输出(在Go Playground上试试):
2018-05-11 00:00:00 +0530 +0530
2018-05-11 00:00:00 +0000 UTC
1525977000
1525996800
另一种选择是使用time.FixedZone()自己构造IST,并使用time.ParseInLocation(),通过我们的手册IST位置:
ist := time.FixedZone("IST", 330*60) // +5:30
t, err := time.ParseInLocation("2006-01-02 MST", "2018-05-11 IST", ist)
输出将是(在Go Playground 上尝试):
2018-05-11 00:00:00 +0530 IST
2018-05-11 00:00:00 +0000 UTC
1525977000
1525996800
另一种选择是按加尔各答市加载印度 IST 区域:
loc, err := time.LoadLocation("Asia/Kolkata")
if err != nil {
panic(err)
}
这将产生相同的输出。试试Go Playground。