Golang如何处理日期和时间_Golang time库使用技巧

11次阅读

time.now() 返回运行环境配置的本地时区时间,但易退化为 utc;格式化与解析必须用“2006-01-02 15:04:05”布局;跨月计算用 adddate();无时区字符串解析须用 parseinlocation()。

Golang 如何处理日期和时间_Golang time 库使用技巧

time.Now() 返回的到底是本地时间还是 UTC?

它返回的是你运行环境配置的本地时区时间,不是 UTC —— 但这个“本地”很脆弱。比如在 Docker 容器里没挂载 /etc/localtime 或没设 TZ=Asia/Shanghaitime.Now() 就会悄悄退化成 UTC 时间,且不报错、不警告。

  • 验证方式:fmt.Println(time.Now().Location()),输出 Local 不代表一定有正确偏移,要看它内部是否加载了真实时区数据
  • 生产环境强烈建议显式绑定时区:shanghai, _ := time.LoadLocation("Asia/Shanghai"),再用 time.Now().In(shanghai)
  • 数据库存储、日志打点、跨服务通信,统一用 time.Now().UTC() 更安全,显示时再转本地

格式化和解析必须用 “2006-01-02 15:04:05″,不能写成实际年份

这不是占位符语法,而是 Go 硬编码的“参考时间布局(layout)”。写成 "2023-01-02""%Y-%m-%d" 都会解析失败或返回零值时间 0001-01-01 00:00:00 +0000 UTC,而 error 可能为 nil(尤其用 ParseInLocation 时),极易埋下静默 bug。

  • 正确写法:t.Format("2006-01-02 15:04:05")time.Parse("2006-01-02", "2026-01-26")
  • 带毫秒:"2006-01-02 15:04:05.000";带时区缩写:"2006-01-02 15:04:05 MST"(注意:MST 是占位符,不是字面量)
  • 字符串含时区偏移(如 "2026-01-26 10:30:00+0800")时,layout 必须含 -0700,否则时区被忽略,按本地解释

加减天数 / 月份要用 AddDate(),别只靠 Add()

Add() 是基于纳秒的线性运算,对“加 1 个月”这种日历语义操作完全无效——比如 1 月 31 日 Add(30 * 24 * time.Hour) 可能落到 3 月 2 日,而不是你想要的 2 月 28 日或 29 日。

  • 改用 t.AddDate(0, 1, 0):加 1 个月,自动处理大小月、闰年
  • AddDate(0, 0, 7) 表示加 7 天,比 Add(7 * 24 * time.Hour) 更准确(避开夏令时跳变等边界)
  • 跨月计算后记得检查有效性:if t.Day() != 31 { /* 原本是 1 月 31 日,加 1 个月后可能变成 2 月 28 日 */}

time.Parse() 默认按 UTC 解析,ParseInLocation() 才真按你指定的时区

这是最常踩的坑:传入 "2026-01-26 10:30:00" 这种无时区字符串,time.Parse("2006-01-02 15:04:05", s) 会把它当 UTC 时间解析,然后你再调 .In(shanghai),结果就比预期快了 8 小时。

立即学习 go 语言免费学习笔记(深入)”;

  • 正确做法:直接用 time.ParseInLocation("2006-01-02 15:04:05", s, shanghai)
  • 如果输入字符串本身带时区(如 "2026-01-26T10:30:00+08:00"),优先用 time.RFC3339 常量,它内置支持时区解析
  • 永远检查 error:if err != nil {/* 别忽略,time.Time{} 是个合法但无意义的零值 */ }

时间处理的复杂点不在 API 多少,而在 layout 字符串和时区绑定这两个地方——写错一个字符、漏一个时区参数,结果可能偏差数小时且难以复现。

text=ZqhQzanResources