AddDate()

引例

AddDate()
20221201

Go Time 包中是这么处理的

AddDate()Format()

只要是涉及到大小月的最后一天都会出现这个问题。

源码分析

10-31 + 1 monthAddDate()month+1Date()
Date()
  • year 2020
  • month 11
  • day 31
  • hour、min、sec、nsec 为运行时的时分秒纳秒

d 计算的是绝对纪元到今天之前的天数:

**d = 今年之前的天数 + 年初到当月之前的天数 + 月初到当天之前的天数;**

最终,将 d 转换成纳秒 + 当天经过的纳秒存储在 Time 对象中。

2022-11-312022-12-012022-11-312022-12-01
2022-11-352022-12-05

预期偏差

我们弄清楚了原理,但仍然不能接受这个结果。这样的结果是 Go 的 bug 吗?还是 Go Time 包偷懒了?

然而并不是,恰恰是我们的“预期”出现了问题。

10-301 month11-3010-311 month11-3010-31+1 month
+1 month
AddDate()

怎么解决

道理我都懂,但我就是想获取上/下一个月的最后一天怎么办?

利用前面源码分析阶段,提到的“天平原理”,就能拿到我们想要的结果。

结语

最初,发现这个问题是看鸟哥文章,当时认为那是 PHP 的“坑”,并没有深入思考过。如今,在 Go 语言再次遇到这个问题,重新思考,发现日期函数本应该就那么设计,是我们对日期函数理解不够,产生了错误的“预期”。

原文链接:https://segmentfault.com/a/1190000042502580