Note 02 / Month arithmetic

1月31日加一个月,为什么不是2月31日

日历里没有 2 月 31 日。按“月”往后推时,遇到短月必须做一次取舍;不同软件的选择可能不同,于是同一个起始日会得到不同结果。

日期推算更新于 2026.10.28

如果把“加一个月”理解成把月份数字加 1,1 月 31 日加一个月就会得到“2 月 31 日”。这个日期不存在,所以真正要回答的问题是:当目标月没有这一天时,应该落到哪里?

最常见的选择:落到目标月最后一天

大多数日历和日期库会采用“月末取整”:先加月份,再把日号缩小到目标月的最后一天。1 月 31 日加一个月,平年落到 2 月 28 日,闰年落到 2 月 29 日;3 月 31 日加一个月,落到 4 月 30 日。

这种规则的好处是可预期。你不会突然跳进下一个月,也不会得到一个不存在的日期。代价是日号发生了变化:从 31 日变成 28 日,之后再减一个月,未必能回到原来的 1 月 31 日。

本站采用月末取整。日期推算器会在结果里提示“已落到该月最后一天”。如果你希望保持“每月最后一天”的规律,下一次推算应该从新的月末日期重新开始。

还有哪些处理方式

一种做法是溢出:把 2 月 28 日之后多出来的几天继续往后数,1 月 31 日加一个月可能变成 3 月 3 日(闰年)或 3 月 2 日。另一种做法是报错,要求用户先修改起始日。也有系统只支持“加 30 天”而不支持“加一个月”,本质上换成了固定天数。

这些规则没有绝对的对错,但它们会在跨系统时产生差异。把同一个日期从表格工具导入数据库,再由另一个程序加一个月,结果可能相差几天。涉及账期、订阅和合同时,最好在文档里写清使用哪一种。

账单和订阅:写日期,不写模糊的“一个月”

如果每月 31 日扣费,到了 2 月就会遇到没有 31 日的问题。常见的商业处理是 2 月按月末扣费,3 月再回到 31 日;也有服务会把扣费日改成 28 日并一直沿用。用户看到的扣款日不同,投诉也会不同。

更明确的写法是:“每月最后一天扣费”或者“每月 28 日扣费”。前者随月份变化,后者固定日号。两种都能避免“2 月怎么办”的争议。对于 30 天免费试用,直接写“自开通起 30 个自然日”比写“一个月”更清楚。

合同日期:四个字段最稳妥

涉及期限时,至少写清起算日、期限长度、计算单位和到期处理方式。例如:“自 2026 年 1 月 31 日起 1 个月,到期日为 2026 年 2 月 28 日;如遇法定节假日,顺延至节假日后第一个工作日。”这样即使对方使用不同软件,也能用写明的到期日核对。

只写“一个月后到期”,虽然日常沟通够用,但遇到月末、闰年和节假日就会产生解释空间。把具体日期写出来,是最省事的消歧方式。

“一个月”和“30 天”不是一回事

1 月 15 日加一个月是 2 月 15 日,间隔 31 天;4 月 15 日加一个月是 5 月 15 日,间隔 30 天;2 月 15 日加一个月是 3 月 15 日,平年间隔 28 天。按月推和按天推只在少数日期上碰巧一致。

如果需求是“30 天后”,就直接加 30 天,不要写成“一个月”。如果需求是“下个月同一天”,就按月推,并提前处理月末。两种需求对应两种按钮,混用会把简单问题变复杂。

几个月末例子

按“月末取整”规则计算,括号内为星期。
起始日期推算结果发生了什么
2026-01-31加 1 个月2026-02-28(六)2 月平年只有 28 天
2024-01-31加 1 个月2024-02-29(四)闰年 2 月有 29 天
2026-03-31加 1 个月2026-04-30(四)4 月只有 30 天
2026-05-31加 3 个月2026-08-31(一)目标月有 31 日,无需取整
2026-08-31加 6 个月2027-02-28(日)跨年并遇到平年 2 月

用自己的日期试一次

打开 日期推算器,把起始日设为 1 月 31 日,单位选“个月”,数量填 1。结果下方会显示目标日期和是否发生月末取整。再换成 30 天,对比两个结果,就能直观看到按月与按天的差别。

如果目标日期用于合同或账单,建议把结果复制下来,再人工核对一次当年 2 月的天数,以及是否涉及法定节假日顺延。工具负责算日期,约定负责说明规则。