python -c "import calendar; print(calendar.monthrange(2026,2)[1])"
python -c "from datetime import date; print(date(2026,2,min(31,28)))"

会员按月续费,1 月 31 日开通的用户到期日算出来是 3 月 3 日,本该是 2 月 28 日。批量续费后这一批人多送了三天。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:很多日期库的 addMonths 先把月份加一,遇到目标月没有这一天就继续往后顺延。1 月 31 日落到 2 月 31 日,再滚到 3 月 3 日,不同语言和版本的行为还不一致。

「月末日期溢出」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。权限不要一口气开到最大,先加到够用再往上试,范围小才好收。

把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。

处理上按这个顺序:业务上先定月末规则 顺延到当月最后一天 还是提前到 28 日;别直接对日期加月 先取当月天数再取 min;只存开始日和周期 到期日现算;把 1 月 29 30 31 三个用例写进测试。

确认没问题再收工,1 月 31 日开通的用户到期日显示 2 月 28 日 不再出现 3 月 3 日。

作者 9823189