使用方法
这个日期差值计算器只有三个输入框——开始日期、结束日期、偏移天数 N,结果随输入自动重算,不需要点按钮,也不会向服务器发任何请求。
- 在「开始日期」填 1990-05-20(示例值),在「结束日期」填 2026-10-01(示例值)。两个框都能直接点日历图标挑,也能手动键入;先发生的那天必須放开始日期。
- 页面打开时已经按这两个示例日期算过一遍,结果卡第一格就是 36 年 4 月 11 天——这是本页的主输出,也是能直接写进合同、简历、工龄说明的写法。
- 第二格给总天数 13283 天,第三格把它拆成 1897 周 4 天。按月汇报、按周汇报、按天汇报三种口径一次到手,不用自己再换算。
- 「偏移天数 N」默认 10000,用来做反向推算:结果卡会同时给出结束日期往前 10000 天是 1999-05-16、往后 10000 天是 2054-02-16。想看一年前后就把 N 改成 365。
- 下方「反向推算表」把 20 组常用天数一次列出,默认先显示前 12 行,点「加载更多」补齐剩下的 8 行;点「复制对照表」按 TSV 复制、「导出 CSV」下载带 BOM 的文件。
- 只想算「到今天多少天」,点一下「结束日期取今天」,结束日期会换成系统当天再重算一遍。
日期差值计算器能解决什么问题
一是把天数翻译成人能读的跨度。社保缴费 13283 天、设备折旧 3652 天、仓库账龄 1500 天,这些数字单独看没有时间感,换成「36 年 4 月 11 天」「10 年」「4 年 1 月 8 天」之后,汇报和写材料都能直接用。
二是算清含首日与不含首日的争议。工期、保修期、试用期这类条款经常在「算不算第一天」上扯皮。本页给的是两端都不含的纯时间差:同一日期差 0 天,相邻两天差 1 天,规则唯一,争议点被消掉。
三是按周汇报的整数拆解。敏捷迭代、租赁周、产线周报要的是「多少个整周外加几天」,本页的第三格直接给出 1897 周 4 天,比 1897.57 周这种小数好写也好核对。
四是反推某个天数对应的是哪天。合同写「交付后 1000 天内完成验收」、活动写「上线 365 天回访」,把天数填进「偏移天数 N」就能立刻看到具体日期,配合推算表还能一次比对 20 个节点。
本页不做这些事:不排除周末和法定节假日(要这个请用页面底部的「工作日计算器」),不做时区换算与时间戳解析,不做倒计时与提醒,也不算「两个日期之间有多少个某星期几」。要按秒、毫秒量级换算请用时间戳转换工具。
计算原理:借位法、UTC 午夜与三个中间量
核心只有两步:把日期换成毫秒时间值相减得到总天数,再用按月加、日钳位的借位法求出「年 / 月 / 天」。第二步是本页与常见的「总天数 ÷ 365」做法最大的区别。
第一步调用的是 Date.prototype.getTime() 的 UTC 毫秒时间值。每个日期先通过 setUTCFullYear(y, m - 1, d) 归一化到当天 UTC 零点,再取毫秒值相减,除以 86400000 得到天数。这里刻意用 UTC 而不是本地时间:中国大陆在 1986 年至 1991 年实行过夏令时,本地午夜相减会出现 23 小时或 25 小时的天,除以一天会得到 0.958 或 1.042 这种小数;UTC 没有夏令时,差值永远是 86400000 的整数倍。
第二步的借位法是这样走的。先算两个日期的月份差 n = (年差 × 12) + 月差,把开始日期加 n 个月(遇到目标月没有该日就钳到月末,例如把 1 月 31 日加 1 个月得 2 月 29 日),如果加完还超过结束日期就把 n 减一,直到不超过为止。剩下的零头再用毫秒差算天数,最后把 n 拆成 Math.floor(n / 12) 年和 n % 12 月。这套「按月加、日钳位」的口径与 moment.js、dayjs 的 diff 一致,所以 2024-01-31 到 2024-03-01 得到的是 1 个月 1 天,而不是 1 个月 −1 天这种负数结果。
三个中间量依次是:①两个 UTC 毫秒时间值 t1、t2;②总天数 Math.round((t2 - t1) / 86400000);③最大整数月数 n 与剩余天数。三个量互相可以校验——把 13283 天除以 7 得 1897.57,与「1897 周 4 天」完全对得上。
完整示例(数字由页面算法实算)
示例条件就是页面打开时的默认值:开始日期 1990-05-20、结束日期 2026-10-01、偏移天数 10000。实测输出如下:
- 总跨度 36 年 4 月 11 天:从 1990-05-20 出发加 36 年得 2026-05-20,再加 4 个月得 2026-09-20,再加 11 天正好落在 2026-10-01;
- 总天数 13283 天:区间里 2 月 29 日一共出现 9 次(1992、1996、2000、2004、2008、2012、2016、2020、2024),这 9 天是「按年数乘 365」会对不上的部分;
- 1897 周 4 天:13283 ÷ 7 = 1897.571,取整 1897 周,余 4 天;
- 反向推算 N = 10000:向前 10000 天是 1999-05-16,向后 10000 天是 2054-02-16——同一天数往前往后得到的日期并不同年,长度也不一样(向前那一段含 2 个闰日,向后那一段含 1 个)。
再拿几个容易吵起来的用例核对一遍口径:2024-01-31 → 2024-03-01 得到 0 年 1 月 1 天(共 30 天),因为 1 月 31 日加 1 个月被钳到 2 月 29 日,再走 1 天;2024-02-29 → 2025-02-28 得到 1 年 0 月 0 天(共 365 天),因为加满 12 个月正好钳到 2 月 28 日;2024-01-01 → 2025-01-01 同样显示 1 年 0 月 0 天,但总天数是 366 天。也就是说「1 年 0 月 0 天」既可能是 365 天也可能是 366 天,跨度写法必须和总天数一起看。
输入范围与常见区间对照表
下表用同一套算法把 12 个常用区间算了一遍,第一行就是页面默认示例。做月报、做合同测算时可以直接查表;要换成别的日期,把值填进上面的输入框即可。
| 区间 | 总跨度 | 总天数 | 整周数与零头 |
|---|---|---|---|
| 1990-05-20 → 2026-10-01(默认) | 36 年 4 月 11 天 | 13283 天 | 1897 周 4 天 |
| 2025-03-01 → 2026-03-01(平年整 1 年) | 1 年 0 月 0 天 | 365 天 | 52 周 1 天 |
| 2024-01-01 → 2025-01-01(闰年整 1 年) | 1 年 0 月 0 天 | 366 天 | 52 周 2 天 |
| 2026-01-01 → 2026-04-01(一个季度) | 0 年 3 月 0 天 | 90 天 | 12 周 6 天 |
| 2026-09-01 → 2026-10-01(一个月整) | 0 年 1 月 0 天 | 30 天 | 4 周 2 天 |
| 2026-09-24 → 2026-10-01(一周整) | 0 年 0 月 7 天 | 7 天 | 1 周 0 天 |
| 2016-10-01 → 2026-10-01(10 年) | 10 年 0 月 0 天 | 3652 天 | 521 周 5 天 |
| 2006-10-01 → 2026-10-01(20 年) | 20 年 0 月 0 天 | 7305 天 | 1043 周 4 天 |
| 1996-10-01 → 2026-10-01(30 年) | 30 年 0 月 0 天 | 10957 天 | 1565 周 2 天 |
| 1976-10-01 → 2026-10-01(50 年) | 50 年 0 月 0 天 | 18262 天 | 2608 周 6 天 |
| 1926-10-01 → 2026-10-01(100 年) | 100 年 0 月 0 天 | 36525 天 | 5217 周 6 天 |
| 1900-01-01 → 2100-01-01(200 年) | 200 年 0 月 0 天 | 73049 天 | 10435 周 4 天 |
表里最有意思的是最后三行:同样写「10 年 0 月 0 天」,总天数却分别是 3652、7305、10957。原因是平年 365 天、闰年 366 天,平均一年 365.2425 天(格里历 400 年共 146097 天、含 97 个闰年),所以 按年数乘 365 永远会少算:十年少 2 天、三十年少 7 天、二百年少 49 天。
结果边界、舍入与闰年规则
下面的数字是刻意定的边界,知道它们能避免把这一页用在它管不到的地方:
- 日期输入限定 1900-01-01 至 2100-12-31。JavaScript 的
Date时间值上限是 ±8.64×10¹⁵ 毫秒,换算过来约 ±1 亿天(公元前 271821 年到公元 275760 年),范围远够用;但输入框把范围收在 1900–2100,是为了避开两个坑:一是 1900 年以前的日历口径(儒略历与前推格里历)容易和史料对不上,二是百年跨度上的「平均年」折算误差会盖过精度本身。 - 总天数恒为整数,不存在 0.5 天。因为两端都归一到 UTC 零点,差值一定是 86400000 的整数倍;8.64×10¹⁵ 也小于
Number.MAX_SAFE_INTEGER(9007199254740991),所以整条链路上没有浮点舍入。若你自己写(t2 - t1) / 86400000后接toFixed(1),在跨夏令时的时区会看到3639.958这种结果,那不是精度问题,是本地时区在作怪。 - 「X 年 Y 月 Z 天」里三个数都不带正负号,方向由输入顺序决定。若把较晚的日期填在「开始日期」,工具会先交换再计算,并在结果里标注方向,不会给出负数跨度。
- 同一天的结果是 0 年 0 月 0 天、0 天,不是 1 天。本页采用两端都不含的纯时间差口径;如果你要的是「含首尾的日历天数」(例如住酒店算头尾两天),把总天数加 1 即可。
- 月份借位按「钳到月末」处理。1 月 31 日加 1 个月是 2 月 29 日(闰年)或 2 月 28 日(平年),不是 3 月 2 日。因此 1 月 31 日到 3 月 1 日的跨度是 1 个月 1 天;到 3 月 31 日则是 2 个月 0 天。
- 闰年判定遵循格里历规则:能被 4 整除、但不能被 100 整除的年份是闰年;能被 400 整除的又是闰年。所以 2000 年 2 月 29 日存在,1900 年和 2100 年都不存在,2100-02-28 到 2100-03-01 只有 1 天。日期记法本身遵循 ISO 8601 的
yyyy-mm-dd扩展格式,历法采用前推格里历(把格里历规则向 1582 年以前外推),与本页输入范围 1900–2100 完全吻合。 - 平摊口径仅供换算,不作为跨度输出。把总天数除以 365.2425 得「约多少年」、除以 30.436875 得「约多少个月」,示例的 13283 天约等于 36.4 年或 436.4 个月。这两个数是四舍五入的近似值,页面上标了「约」字,不能和「36 年 4 月 11 天」混用。
常见问题
为什么「1 年 0 月 0 天」有时是 365 天、有时是 366 天?
因为跨度的「年 / 月」是按日历借位算的,而总天数是按实际日历天数加的。2024-01-01 到 2025-01-01 跨过 2024-02-29,所以是 366 天;2025-03-01 到 2026-03-01 没跨到 2 月 29 日,就是 365 天。两者都写作 1 年 0 月 0 天。写合同时要避免歧义,最佳做法是同时写上跨度与总天数。
输入框里的日期手动键错了会怎样?
会给出具体报错而不是静默归零。工具要求格式为 YYYY-MM-DD,年份在 1900–2100 之间,并且会回读校验:填 2024-02-30 这类不存在的日期会被拦下,因为 JavaScript 会把它滚成 3 月 1 日,回读时月份或日号对不上。空值、只填年份、以及开始日期晚于结束日期,都会各自给出对应提示。
为什么不直接写「相差多少天」就够了?
因为天数无法表达跨度。13283 天可以是任何长度的区间,而「36 年 4 月 11 天」能立刻看出量级;反过来,跨度的「年 / 月」在借位处会有歧义(1 月 31 日到 3 月 1 日算 1 个月 1 天还是 0 个月 30 天),天数则没有歧义。两套口径各有用途,所以本页同时给出,而不是二选一。
2024-01-31 到 2024-03-01 为什么不是「1 个月 0 天」?
因为 1 月 31 日加 1 个月,2024 年是闰年,目标 2 月没有 31 日,会被钳到 2 月 29 日;从 2 月 29 日到 3 月 1 日还剩 1 天,所以是 1 个月 1 天。若换成平年(2025-01-31 到 2025-03-01),钳位结果是 2 月 28 日,剩 1 天,跨度同样是 1 个月 1 天,但总天数从 30 天变成 29 天。
跨夏令时的地区会算错吗?
不会。所有运算都走 UTC 毫秒时间值,getUTCFullYear / getUTCDate 只读 UTC 字段,与本机时区无关。中国大陆 1986–1991 年实行过夏令时,用本地时间相减会出现 23 或 25 小时的天;本页从源头避开了这个坑,因此在任何时区的浏览器里结果都一致。
能把结果当成「还剩多少天」的倒计时吗?
可以作为天数来源,但它不含倒计时逻辑,也不会自动刷新到今天。要做倒计时或提醒,请用页面底部的「天倒计时计算器」;要算「距今多少天」,把结束日期设成今天即可,页面上有「结束日期取今天」按钮可以一键完成。
为什么不算工作日,也不排除节假日?
因为日历差值和排班是两件事:前者只跟日历有关,后者取决于周末定义、法定节假日名单和调休补班日。本页刻意只做前者,把后者留给专门的工作日工具,两边各自口子清晰,不会出现「同一个区间两个工具给出不同天数」的困惑。要排周末和节假日,请用页面底部的「工作日计算器」。
输入的两个日期会传到服务器吗?
不会。这个日期差值计算器全程只调用浏览器本地的 Date 对象,页面没有任何网络请求,也不写浏览器存储,刷新后输入框会回到默认的示例日期。想自己核实,打开开发者工具的 Network 面板,改几次日期看看有没有新请求发出即可。
相关工具
- 工作日计算器:在日历差值的基础上排除周末与法定节假日,还能算「第 N 个工作日」是哪天。
- 日期加天数计算器:只做单向加法,输入起始日加天数直接得到目标日期,比本页的推算表更直接。
- 闰年判断工具:单独判断某一年是不是闰年,核对本页「平年 365 天、闰年 366 天」的差从哪来。
- 年龄计算器:按生日算周岁、虚岁与出生天数,用的是同一套借位法。
- 距今天数计算器:固定把结束日期当作今天,专门回答「这件事到今天多少天了」。
- 周数字计算器:求某一天属于当年的第几周,做周报编号时与本页的整周数配套使用。
- 日期格式化转换器:把日期换成各种字符串格式,例如把 2026-10-01 写成 2026 年 10 月 1 日。
- 日期时间:查看全部日期时间工具。