Go中计算两日期天数差需用time.Sub得Duration后除以24*time.Hour,注意时区一致和later.Sub(earlier)顺序,结果为整数截断而非四舍五入。

用 time.Sub 得到 time.Duration,再转成天数
Go 里没有直接“两个日期相减得天数”的函数,必须先用 Sub 拿到时间差,再手动换算。核心逻辑是:用后一个时间减前一个时间得到 Duration,然后除以 24 * time.Hour。
- 注意顺序:
later.Sub(earlier)才是正数;反过来会是负的Duration -
Duration是纳秒级精度,但除法截断只保留整数部分(不是四舍五入) - 如果需要向上取整(比如跨了 23 小时也算一天),得自己加判断逻辑
earlier := time.Date(2024, 1, 15, 0, 0, 0, 0, time.UTC) later := time.Date(2024, 1, 18, 12, 0, 0, 0, time.UTC) diff := later.Sub(earlier) // 78h days := int(diff / (24 * time.Hour)) // 得到 3,不是 3.25
别用 time.Date 的年月日字段手动算——容易出错
有人想拆解年、月、日自己做减法,比如 year2-year1 再乘 365,再加月份天数……这在 Go 里完全没必要,而且极易翻车。
- 闰年、大小月、时区偏移、夏令时都会让手动计算失效
-
time.Date构造时若传入非法日期(如 2 月 30 日),Go 会自动归一化(变成 3 月 2 日),但你未必意识到 - 只要用
time.Time值本身做Sub,底层已处理所有历法规则
注意时区:同一时刻在不同时区可能差一天
time.Time 带时区信息,Sub 计算的是绝对时间差,但如果你从字符串解析时间却忽略时区,结果就不可靠。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 用
time.ParseInLocation显式指定时区,别依赖Parse的本地时区默认行为 - UTC 时间最安全;如果业务固定用东八区,统一用
time.FixedZone("CST", 8*60*60) - 错误示例:
time.Parse("2006-01-02", "2024-01-01")解析出来是本地时区,部署到美国服务器就可能差一天
性能和边界:大跨度日期差不会溢出,但要注意负值处理
time.Duration 是 int64,单位是纳秒,能表示约 ±290 年,日常完全够用。真正要留心的是逻辑分支。
立即学习“go语言免费学习笔记(深入)”;
- 如果
earlier.After(later),Sub返回负值,int(diff / ...)也会是负数 - 业务上是否允许负天数?要不要取
abs?得看场景,比如倒计时和历史回溯逻辑完全不同 - 不要用
diff.Hours() / 24,因为Hours()返回float64,有精度丢失风险(纳秒转浮点可能丢精度)
实际写的时候,多数情况一行就能搞定:int(t2.Sub(t1) / (24 * time.Hour)),但得确保 t1、t2 都是你要比对的那个时区下的有效 time.Time。时区和正负号,这两个点漏掉一个,结果就悄悄错了。

















