Golang time.Format 时间少了8小时?
1. 前端传参
可知前端使用 new Date().toISOString()
方法
该方法会将时间转换为 UTC 标准时间
2. 后台收参
注意看上面这张图的右边, 比较有意思
代码是这样的:
if start != nil {
query.Where("front_account_info.created_at>?", start)
countSql += " and a.created_at > '" + start.In(time.Local).Format("2006-01-02 15:04:05") + "'"
logger.Debug("带Local格式化时间:", start.In(time.Local).Format("2006-01-02 15:04:05"))
logger.Debug("直接格式化时间:", start.Format("2006-01-02 15:04:05"))
}
3. 通过比对得出结论
- time.Format 函数在直接调用的时候是会处理时区信息的 (前端传参有带上时区信息为 UTC 时间, 需要转换为+8时间)
- start 本身是带着时区信息的, 可以看上图
[]interface{}
传参部分中的time.Date(2022, time.February, 28, 16, 0, 0, 0, time.UTC)
, time.UTC即为时区信息 - 需要带本地时区的 Format, 即 GMT+8 的, 必须调用
time.In(time.Local).Format()
或者time.Local().Format()
, 在time包源码中可得知这两种是等效的
// Local returns t with the location set to local time.
func (t Time) Local() Time {
t.setLoc(Local)
return t
}
// In returns a copy of t representing the same time instant, but
// with the copy's location information set to loc for display
// purposes.
//
// In panics if loc is nil.
func (t Time) In(loc *Location) Time {
if loc == nil {
panic("time: missing Location in call to Time.In")
}
t.setLoc(loc)
return t
}
4. 结论
- 有 orm 的情况下不要使用裸SQL
- 裸SQL避免不了的情况下不要使用
time.Format
, 除非传过来的是 +8 时区 - 裸SQL+时间都避免不了的情况下, 一定使用
time.In(time.Local).Format()
进行本地时区转换