先上代码
准备获得一个我们的双十一的时间 2021-11-11 00:00:00
t, _ := time.Parse("2006-01-02 15:04:05", "2021-11-11 00:00:00")
tStr := t.Format("2006-01-02 15:04:05")
timestamp := t.Unix()
fmt.Println(t, "||", tStr, "||", timestamp)
// 2021-11-11 00:00:00 +0000 UTC || 2021-11-11 00:00:00 || 1636588800
打开时间戳工具 Unix时间戳(Unix timestamp)转换工具 - 站长工具
发现时间戳 1636588800 对应的时间是 2021-11-11 08:00:00,比预期的多了 8 小时。
问题分析
再仔细看一下,打印的 time 里面 2021-11-11 00:00:00 +0000 UTC 是 UTC 的时间。看起来这个 Parse 时间没有考虑时区,当做默认的 +0 时区 UTC 时间来解析了,就造成了实际时间比预期的 +8 小时(在国内机器上执行这段代码)。
为了好理解这里列一下转换关系:
2021-11-11 00:00:00 +0800 CST // 预期时间
2021-11-10 16:00:00 +0000 UTC // 预期时间对应的 UTC 时间
2021-11-11 00:00:00 +0000 UTC // Parse 到的时间
2021-11-11 08:00:00 +0800 CST // Parse 到的时间的等效 CST 时间
解决办法
怎么解决呢?
有两个办法,在 time string 中加上时区信息来解析:
t, _ := time.Parse("2006-01-02 15:04:05 -0700 MST", "2021-11-11 00:00:00 +0800 CST")
tStr := t.Format("2006-01-02 15:04:05")
timestamp := t.Unix()
fmt.Println(t, "||", tStr, "||", timestamp)
// 2021-11-11 00:00:00 +0800 CST || 2021-11-11 00:00:00 || 1636560000
或者使用 time.ParseInLocation 方法:
t, _ := time.ParseInLocation("2006-01-02 15:04:05", "2021-11-11 00:00:00", time.Local)
tStr := t.Format("2006-01-02 15:04:05")
timestamp := t.Unix()
fmt.Println(t, "||", tStr, "||", timestamp)
// 2021-11-11 00:00:00 +0800 CST || 2021-11-11 00:00:00 || 1636560000
这里直接使用了 time.Local,会根据系统配置来,如果需要自定义的话,也可以自己设置,比如:
location, err := time.LoadLocation("Asia/Shanghai")
这里得到的 location 和 time.Local 类型相同。