Go 的 time.Format 必须使用“2006-01-02 15:04:05”作为布局字符串,因其是硬编码的参考时间(2006年1月2日15:04:05 MST),所有 layout 必须与之格式严格一一对应,否则原样输出不报错。

Go 里 time.Format 不是“按需填空”,而是严格依赖固定布局字符串——填错一个字符,结果就完全不对,而且不报错。
为什么 time.Format 必须用 "2006-01-02 15:04:05" 这串数字?
这不是随便选的日期,而是 Go 源码里硬编码的“参考时间”:2006 年 1 月 2 日下午 3 点 4 分 5 秒(MST 时区)。所有 layout 字符串都必须和这个时间的格式一一对应。
常见错误现象:time.Now().Format("yyyy-MM-dd HH:mm:ss") 看起来很熟悉,但 Go 会原样输出那串字符串,不会替换成真实时间——因为 Go 不认这些占位符。
- 正确写法只认
"2006-01-02 15:04:05"及其子集(比如"2006-01-02"、"15:04") - 小时必须用
15(24 小时制),03是 12 小时制带前导零,3是不带零的 12 小时制 - 年份只能用
2006,写成YYYY或yyyy就失效 - 中文环境容易误把
星期一写进 layout,但 Go 默认 layout 不支持中文 weekday,得靠time.Weekday.String()单独处理
time.Format 在不同时区下输出结果不同,但函数本身不改时区
time.Format 只负责“把当前 time.Time 值按 layout 渲染成字符串”,它不改变时间值本身。真正影响输出的是这个 time.Time 对象绑定的时区(Location)。
立即学习“go语言免费学习笔记(深入)”;
使用场景:你想显示东八区时间,但 time.Now() 返回的是本地时区(可能不是 Asia/Shanghai)。
- 别直接
time.Now().Format(...),先用time.LoadLocation("Asia/Shanghai")加载时区,再调用.In(loc) - 注意
time.FixedZone("CST", 8*60*60)可以创建固定偏移时区,但不会自动适配夏令时 - 如果传入的是 Unix 时间戳转的
time.Unix(...),它默认绑定time.UTC,不加.In(loc)就永远显示 UTC 时间
性能敏感场景下,避免重复解析 layout 字符串
time.Format 每次调用都会内部解析 layout 字符串。虽然单次开销小,但在高频日志或 HTTP 响应头生成中,反复调用 t.Format("2006-01-02T15:04:05Z07:00") 会有可测的分配和 CPU 成本。
实操建议:
- 把常用 layout 提前定义为常量:
const RFC3339NoSec = "2006-01-02T15:04Z07:00" - 不要在循环里拼接 layout(如
t.Format("2006-01-02 " + suffix)),拼接本身有额外开销且破坏常量优化 - 极端情况(如每秒数万次格式化)可考虑用
fmt.Sprintf+ 手动拆解t.Year()、t.Month()等,但要自己处理前导零和时区,容易出错
最容易被忽略的是:layout 字符串里的空格、冒号、连字符全是字面量,不能省略或替换。比如想输出 2024/05/20,必须写 "2006/01/02",写成 "2006/1/2" 就会导致月份和日期不补零,输出变成 2024/5/20——而你很难立刻意识到这是 layout 写错了,不是时间值的问题。


















