日期计算

计算两日期相差的天/周/月/年,以及指定日期加减天、月、年的结果。

—

日期加减

—

日期计算:天数为什么精确、月份为什么只能估算

天数精确,月年不精确

两个日期之间的天数可以精确算出——它就是两个时间点之间的绝对间隔,没有任何歧义(前提是明确了是否包含端点)。

但"相差几个月"没有唯一答案,因为月份长度不同:

区间天数"几个月"
1 月 1 日 → 2 月 1 日311 个月
2 月 1 日 → 3 月 1 日28 或 291 个月
1 月 1 日 → 1 月 31 日30不满 1 个月

同样是"1 个月",天数可以是 28 到 31。所以工具的做法是:天数给出精确值,月和年按平均长度换算并明确标注为估算(月按 30.44 天、年按 365.25 天)。这样你不会看到 30 和 31 都被说成"1 个月"却不知道依据。

需要精确的"几个月"时,不要用换算,而应该按日历规则算:逐月推进,遇到月末做相应处理(1 月 31 日加一个月是 2 月 28 日还是 3 月 2 日,各系统实现不同)。工龄、租期、账单周期这类场景应该用日历法,差额通常是几天。

加减月份的月末溢出

日期加减里最容易出错的是月份处理:

操作结果说明
3 月 31 日 + 1 个月4 月 30 日目标月没有 31 日,退回月末
1 月 31 日 + 1 个月2 月 28 日(闰年 29 日)同上
2 月 29 日 + 1 年2 月 28 日非闰年没有 2 月 29 日

工具有按日历规则处理这类溢出。注意这不是唯一正确的实现:有的系统选择"溢出到下个月"(3 月 31 日 + 1 个月 = 5 月 1 日)。做合同到期日、账单日、订阅续费日期计算时,必须先确认业务规则要求哪一种。

需要明确的四个约定

  1. 是否包含边界日期。"1 日到 3 日有几天",可能是 2 天(间隔)也可能是 3 天(含首尾)。请假天数、住宿晚数、项目工期,各自的口径不同。这是日期计算出错的头号原因。
  2. 时区。纯日期(不带时间)通常没有时区问题,但一旦涉及"今天""现在"就会受影响。跨时区的服务器按 UTC 计算"今天",可能与你本地日期差一天。日期选择器返回的是本地日期时尤其要注意。
  3. 工作日与自然日。"相差 30 天"和"30 个工作日"完全不同。工作日计算需要排除周末和法定节假日,而节假日因地区和年份而异,必须用对应的日历数据,不能靠规则推算。
  4. 夏令时。在有夏令时的地区,某些日期实际是 23 或 25 小时。纯日期运算不受影响,但涉及"几点到几点"的时长计算会差一小时。中国不实行夏令时,所以国内业务可以忽略这一条。

实际应用

工具怎么用

上半部分选起始和结束日期,得到精确相差天数以及周/月/年的估算值;下半部分选基准日期并填要加减的天数、月数、年数,得到目标日期。两部分都实时计算,日期运算在浏览器本地完成。

常见问题

月和年是怎么算出来的?

天数是精确值;周=天/7;月按平均 30.44 天、年按 365.25 天估算,便于快速参考,非日历精确月。

加减月份会跨年吗?

会。工具直接用 Date 的 setMonth/setFullYear,遵循日历规则自动跨年、处理月末溢出。