time.unix() 是唯一推荐的 unix 时间戳转 time.time 方式,接受秒和纳秒参数,默认返回本地时区时间;utc 场景需链式调用 .in(time.utc),毫秒/微秒级推荐 go 1.17+/1.19+ 的 unixmilli()/unixmicro(),字符串时间戳须先 parseint 再转换。

time.Unix() 是唯一推荐的转换方式
Go 标准库只提供 time.Unix() 这一个安全、语义明确的 Unix 时间戳转 time.Time 的入口。它接受秒数和纳秒数两个整数参数,返回本地时区(非 UTC)的 time.Time 对象。
常见错误是直接用 time.Unix(1717027200, 0) 却没意识到结果带本地时区偏移——比如东八区会显示 2024-05-31 08:00:00 +0800 CST,而非 UTC 的 00:00:00 +0000 UTC。
- 如果时间戳来自后端 API 或数据库(通常为 UTC),应显式指定 UTC 时区:
time.Unix(1717027200, 0).In(time.UTC) - 秒级时间戳就传
0作纳秒参数;毫秒级需先转成秒+纳秒:ms := int64(1717027200123); sec := ms / 1000; nsec := (ms % 1000) * 1e6; t := time.Unix(sec, nsec) - 别用
time.Date()手动拼年月日——易出错、不处理闰秒、忽略时区逻辑
time.UnixMilli() 和 time.UnixMicro() 更简洁但有版本限制
Go 1.17+ 提供了 time.UnixMilli() 和 Go 1.19+ 的 time.UnixMicro(),直接接收毫秒/微秒级整数,内部自动拆解为秒+纳秒。省去手动计算,可读性更好。
但要注意:低于对应版本会编译失败,CI 或旧环境容易踩坑。
- Go 1.17 前只能用
time.Unix()+ 手动换算 -
time.UnixMilli(ms)等价于time.Unix(ms/1000, (ms%1000)*1e6),但更可靠(处理负数毫秒时行为一致) - 它们默认也返回本地时区时间,UTC 场景仍需链式调用
.In(time.UTC)
解析字符串时间戳?先转整数再用 Unix(),别用 Parse()
如果原始数据是字符串形式的数字(如 "1717027200" 或 "1717027200123"),必须先用 strconv.ParseInt() 转成 int64,再交给 time.Unix() 或其变体。
千万别试图用 time.Parse() 去“解析”纯数字字符串——它只认格式化的时间字符串(如 "2006-01-02"),对数字串会直接报 parsing time "1717027200" as "2006": cannot parse "1717027200" as "2006" 错误。
- 示例:
ts, _ := strconv.ParseInt("1717027200123", 10, 64); t := time.UnixMilli(ts) - 记得检查
ParseInt的 error,空字符串或超范围会返回 0,导致时间变成 Unix 零点(1970-01-01) - JSON 反序列化时,若字段是字符串类型的时间戳,需自定义
UnmarshalJSON方法做这步转换
时区是最大隐性变量,不显式处理就会埋雷
Go 的 time.Time 内部存的是 UTC 时间,但打印或格式化时默认按本地时区渲染。同一个 time.Time 值,t.String() 和 t.In(time.UTC).String() 输出完全不同。
服务间传递时间戳、写入数据库、前端展示,几乎都要求明确时区语义。忽略这点,会导致定时任务早 8 小时触发、日志时间对不上、跨时区用户看到错误日期。
- 入库前统一转 UTC:
t.In(time.UTC),避免依赖数据库时区配置 - HTTP 响应中返回时间戳时,优先用
t.UTC().UnixMilli(),而非本地时间的t.UnixMilli() - 测试时用
time.Now().UTC()生成基准值,避免本地时区干扰 CI 环境
事情说清了就结束
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











