使用方法
- 在「数值」填 100(示例值),允许 0.01~1000000 之间的小数;在「输入单位」选「天」。
- 「起始日期」填 2026-03-01(示例值)。它在三种口径下起作用:算「日历月」时要从这里逐月往后推,算「落点日期」时要拿它加天数,算「加载更多」后的整张对照表也以它为锚点。只算周、30 天制月和公历平均月的话,这一格不影响结果。
- 按 Enter 或点「开始换算」。结果区 12 张卡片同时给出总天数、周 + 天、周数小数、三种月数、两种年数、日历月、落点日期、小时与分钟。
- 看「月(30 天制)」和「月(公历平均)」这两张卡片:同一批天数,两个数不相等,这就是本页最重要的口径差别。100 天是 3.3333 个 30 天制月,却只有 3.2855 个公历平均月,差了约 1.46 天。
- 「日历月(自锚点)」这一格给出的是最贴近日常说法的答案:从起始日期起最多能推几个整月、还剩几天。100 天从 2026-03-01 起是 3 个月 8 天,落点是 2026-06-09。
- 下方对照表共 20 行,先显示 12 行,点「加载更多」展开其余 8 行;「导出 CSV」自带 BOM,Excel 双击不乱码;「复制对照表」复制的是制表符分隔的 TSV,可直接粘进表格。
- 点「重置为默认示例」随时回到「100 天 / 2026-03-01」这组默认值。
这个天周计算器能解决什么问题
一是把「几个月」这句话变成可核对的数字。合同写「三个月内交付」,90 天、92 天还是 91 天?本页告诉你:90 天是 3 个整 30 天制月,但从 2026-03-01 起算的 90 天只有 2 个月 29 天,因为三月有 31 天。要签合同、算工期、排交付节点时,先确认用的是哪一种月,比事后争论便宜得多。
二是对齐两套常见惯例。会计与金融常用 30 天制月、360 天年(ISDA 30/360 天数计算惯例),排期与日历常用真实的日历月和格里高利年。本页把两套并排显示,同一批天数在两个体系里各是多少个月、差几天,一眼可见,不用来回换工具。
三是反推落点日期。给一个起点和一批天数,直接给出终点日期;给一个起点和一个整月数,也能通过「日历月」这一格换成天数。做项目排期、试用期到期、贷款首期还款日这类计算时,比在日历上一格一格数可靠。
四是做量纲检查。写报表、看数据字典时经常遇到「这个字段是周还是天」的疑问。把数值丢进来换算一遍,能立刻发现单位用错了:1 个月被当成 4 周(其实是 4.3481 周),100 天被当成 3 个月(其实是 3 个月 8 天),这类错在图表里会放大成明显的偏差。
本页不做这些事:不做闰秒处理,不算工作日与节假日(那是「工作日计算器」的活),不做时区换算,也不做时间戳解析。它只处理「天、周、月、年」这四个时间长度单位之间的折算。
原理:先统一折成天数,再按四种月长分流
调用的函数与算法。这个天周计算器不用任何天文库,核心只有三样:JavaScript 的 Date 构造器(按本地日历建日期)、一个自定义的月末夹取函数 addMonthsClamp()、以及一个逐月递减的循环——while (diffDays(锚点, addMonthsClamp(锚点, k + 1)) <= 天数) k++,把 k 推到「再加一个月就超过总天数」为止,剩下的就是余天数。日差用 Math.round((后 − 前) / 86400000) 计算,取整是为了吸收夏令时造成的 23/25 小时偏差。
为什么用月末夹取,而不是直接加月。JavaScript 的 setMonth() 是溢出式的:1 月 31 日加一个月会得到 3 月 3 日(因为 2 月 31 日不存在,就往后溢出)。这和大多数人对「一个月后」的直觉不符。本页先把目标月的 1 号建出来,查清这个月有多少天,再取 Math.min(原日号, 该月天数),于是 1 月 31 日加一个月得到 2 月 28 日(闰年是 29 日),1 月 31 日加三个月得到 4 月 30 日。差异是实打实的:直接加月给 3 月 3 日,夹取给 2 月 28 日,整整差了三天。
五个常数分别是怎么来的。30 天制月取整数 30,来自会计与债券计息惯例:一年按 360 天、一月按 30 天。公历平均月取 365.2425 ÷ 12 = 30.436875 天,其中 365.2425 来自格里高利历的闰年规则——每 400 年有 97 个闰年,共 400 × 365 + 97 = 146097 天,除以 400 就是 365.2425。朔望月取 29.530588853 天,也就是 29 天 12 小时 44 分 3 秒,这是月相从新月到下一次新月的时间间隔,属于天文常数,和公历的月份没有任何对应关系。年长则给两个:365 是平年天数,365.2425 是格里高利平均年长。
遵循的标准。周的长度依据 ISO 8601:1 周恒为 7 天,周一是一周的第一天,且「第 1 周」定义为包含 1 月 4 日的那一周——这解释了为什么跨年时第 1 周可能落在上一年的 12 月。公历的闰年规则同样来自格里高利历:能被 4 整除的年份是闰年,但整百年必须能被 400 整除才算,所以 2000 年是闰年而 1900 年不是。30 天制月的依据是 30/360 天数计算惯例,债券市场的应计利息至今按它算。
边界与阈值都是具体数字。输入上限 1000000,因为它已经相当于 2739.7 个平年,再大就没有现实意义。JavaScript 的 Date 能表示的范围是 ±8.64×1015 毫秒,换算过来是 ±100000000 天,约 ±273791 年;本页在算出终点日期后检查 isNaN(),一旦超界立刻报错而不是显示 Invalid Date。日差用毫秒除以 86400000,在 100 万天这个量级上误差远小于半毫秒,取整不会出错;1000000 × 86400 = 86400000000 秒远小于 253 = 9007199254740992,所以整数运算不会丢精度。
常见误用纠正三条。第一,把「1 个月」当成 4 周:1 个公历平均月是 30.436875 ÷ 7 = 4.3481 周,按 4 周算,一年会少掉约 6.2 天。第二,把 30 天制月当作日历月:100 天按 30 天制是 3.3333 个月,按日历推是 3 个月 8 天,两者不是同一件事。第三,用 setMonth() 直接做「加 N 个月」的运算,遇到 29、30、31 日的起始日期就会溢出到下个月初,本页的月末夹取就是为了绕开这个坑。
完整示例(默认的 100 天 / 起始日期 2026-03-01)
页面打开时的默认值是 数值 100、单位「天」、起始日期 2026-03-01,结果卡片与对照表第 13 行完全对应,也是这个天周计算器唯一一处「三处咬合」的示例值。同一个 100 天,五套口径算出来是这样:
- 周:
100 ÷ 7 = 14.2857周,也就是 14 个整周余 2 天; - 月(30 天制):
100 ÷ 30 = 3.3333个月; - 月(公历平均):
100 ÷ 30.436875 = 3.2855个月; - 月(朔望月):
100 ÷ 29.530588853 = 3.3863个月; - 日历月(自 2026-03-01):先推 1 个月到 4 月 1 日(31 天)、2 个月到 5 月 1 日(61 天)、3 个月到 6 月 1 日(92 天),再推 4 个月是 7 月 1 日共 122 天,已经超过 100,所以停在 3 个月,剩
100 − 92 = 8天,写作 3 个月 8 天; - 落点日期:2026-03-01 加 100 天是 2026-06-09,与「3 个月 8 天」的算法完全吻合;
- 年:
100 ÷ 365 = 0.2740年(365 天制);100 ÷ 365.2425 = 0.2738年(格里高利),两者差 0.0002 年,约 1.8 小时; - 小时与分钟:
100 × 24 = 2400小时,100 × 1440 = 144000分钟。
把这张清单和结果卡片对照着看,会发现一个容易忽略的点:三种「月」的口径给出三个不同的数,差值最大能到 1 天以上。100 天在 30 天制下是 3.3333 个月,在公历平均月下是 3.2855 个月,相差 0.0478 个月,折算回来正好是 0.0478 × 30.436875 ≈ 1.46 天。所以凡是要写进文档的「几个月」,都值得先确认口径。
天数周数月数换算对照表
下表以 2026-03-01 为锚点(与页面默认值一致),把常见天数一次性换算到六种口径。前 12 行直接显示,其余 8 行点「加载更多」。表中的「日历月」列随起始日期变化,改一下起始日期再点「开始换算」,整张表会跟着重算。
| 天数 | 周 + 天 | 月(30 天制) | 月(公历平均) | 月(朔望月) | 年(365 天制) | 日历月(自锚点) | 落点日期 |
|---|---|---|---|---|---|---|---|
| 1 | 0 周 1 天 | 0.033 | 0.033 | 0.034 | 0.003 | 0 个月 1 天 | 2026-03-02 |
| 2 | 0 周 2 天 | 0.067 | 0.066 | 0.068 | 0.005 | 0 个月 2 天 | 2026-03-03 |
| 3 | 0 周 3 天 | 0.100 | 0.099 | 0.102 | 0.008 | 0 个月 3 天 | 2026-03-04 |
| 7 | 1 周 0 天 | 0.233 | 0.230 | 0.237 | 0.019 | 0 个月 7 天 | 2026-03-08 |
| 10 | 1 周 3 天 | 0.333 | 0.329 | 0.339 | 0.027 | 0 个月 10 天 | 2026-03-11 |
| 14 | 2 周 0 天 | 0.467 | 0.460 | 0.474 | 0.038 | 0 个月 14 天 | 2026-03-15 |
| 21 | 3 周 0 天 | 0.700 | 0.690 | 0.711 | 0.058 | 0 个月 21 天 | 2026-03-22 |
| 30 | 4 周 2 天 | 1.000 | 0.986 | 1.016 | 0.082 | 0 个月 30 天 | 2026-03-31 |
| 31 | 4 周 3 天 | 1.033 | 1.019 | 1.050 | 0.085 | 1 个月 0 天 | 2026-04-01 |
| 45 | 6 周 3 天 | 1.500 | 1.478 | 1.524 | 0.123 | 1 个月 14 天 | 2026-04-15 |
| 60 | 8 周 4 天 | 2.000 | 1.971 | 2.032 | 0.164 | 1 个月 29 天 | 2026-04-30 |
| 90 | 12 周 6 天 | 3.000 | 2.957 | 3.048 | 0.247 | 2 个月 29 天 | 2026-05-30 |
| 100 | 14 周 2 天 | 3.333 | 3.285 | 3.386 | 0.274 | 3 个月 8 天 | 2026-06-09 |
| 120 | 17 周 1 天 | 4.000 | 3.943 | 4.064 | 0.329 | 3 个月 28 天 | 2026-06-29 |
| 180 | 25 周 5 天 | 6.000 | 5.914 | 6.095 | 0.493 | 5 个月 27 天 | 2026-08-28 |
| 365 | 52 周 1 天 | 12.167 | 11.992 | 12.360 | 1.000 | 12 个月 0 天 | 2027-03-01 |
| 500 | 71 周 3 天 | 16.667 | 16.427 | 16.932 | 1.370 | 16 个月 13 天 | 2027-07-14 |
| 1,000 | 142 周 6 天 | 33.333 | 32.855 | 33.863 | 2.740 | 32 个月 24 天 | 2028-11-25 |
| 10,000 | 1428 周 4 天 | 333.333 | 328.549 | 338.632 | 27.397 | 328 个月 16 天 | 2053-07-17 |
| 1,000,000 | 142857 周 1 天 | 33333.333 | 32854.884 | 33863.192 | 2739.726 | 32854 个月 26 天 | 4764-01-27 |
从表里能读出三个规律。第一,30 天制月与公历平均月的差距随天数线性放大:100 天差 0.048 个月,1000 天差 0.478 个月,100 万天差 479.449 个月(约 39.9 年),所以小额场景可以忽略,长期场景绝不能混用。第二,「日历月」的余数会跳变:60 天是 1 个月 29 天,再多一天成 61 天就变成 2 个月 0 天,因为四月只有 30 天,跨过月末就会进位。第三,365 天不恰好等于 12 个日历月,从 2026-03-01 起算的 365 天确实落在 2027-03-01,正好 12 个月,但日历月计数依赖具体起止日期,换一个锚点就可能变成 12 个月零几天。
输入范围、边界与舍入说明
- 数值限 0.01~1000000,允许两位小数。0 和负数会被拒绝——天数为零时周数和日历月都无从换算;超过 100 万则已经不具现实意义(相当于 2739.7 年)。
- 单位只接受四种:天、周(7 天)、月(30 天制)、年(365 天制)。选「月(30 天制)」输入 3,得到的是 90 天,不是三个日历月;想按日历月算,请把单位选「天」并填好起始日期。
- 起始日期限 1900-01-01 到 2200-12-31,且必须是真实存在的日期。填 2026-02-30 会被拒绝,因为 2 月没有 30 日——这里用的是「回读校验」:把年月日建成 Date 对象后再读回来,只要三项中任何一项对不上,就判定为非法日期。
- 小时与分钟按四舍五入取整。输入 0.5 天得到 12 小时;输入 1.005 天,小时数是
Math.round(24.12) = 24,分钟数是Math.round(1447.2) = 1447,与 24 小时并不严格自洽。想要严格自洽的换算,请把「数值」的单位统一成小时或分钟再算。 - 月数与年数保留 4 位小数,对照表保留 3 位。4 位够区分「月(365 天制)」与「月(格里高利)」这种只差万分之几的口径;3 位是为了让 100 万天那一行的总宽度不溢出。四舍五入只是显示层的处理,中间计算全程用双精度浮点数,不会被截断。
- 日历月的月末夹取规则:先把目标月的 1 号建出来、查出该月天数,再取「原日号」与「该月天数」中的较小值。所以 1 月 31 日加一个月是 2 月 28 日(闰年 2 月 29 日),3 月 31 日加一个月是 4 月 30 日。这与 JavaScript
setMonth()的溢出行为(3 月 31 日 → 5 月 1 日)不同,本页刻意选了前者,因为它更符合日常语义。 - 日差用毫秒差除以 86400000 后四舍五入。这样处理是为了抵消夏令时:有夏令时的地区,某一天可能是 23 小时或 25 小时,直接相除会出现 0.96 或 1.04 这类小数。中国境内没有夏令时,影响为零。
- 超出 Date 表示范围时会报错。JavaScript 的
Date上限是 ±8.64×1015 毫秒,约 ±1 亿天、±27.4 万年。这个天周计算器在算出落点日期后检查有效性,一旦越界就给出提示而不是显示Invalid Date。
常见问题
100 天到底是 3 个月还是 3.33 个月?
取决于你问的是哪一种月。30 天制月下是 3.3333 个月(会计、债券计息用这套);公历平均月(30.436875 天)下是 3.2855 个月;按日历从 2026-03-01 起算则是 3 个月 8 天。三个数都不算错,错的是不说明口径就写「3 个月」。要写进合同或工期表时,建议直接写「100 天」或「自某日起 3 个月 8 天」。
为什么「日历月」必须填一个起始日期?
因为日历月的长度本身不固定:28、29、30、31 天都有。「3 个月」是 89 天还是 92 天,完全取决于从哪一天开始。不给锚点,这个换算就没有唯一答案。本页把起始日期做成必填,就是为了让「几个月」这个说法始终有一个可复现的基准;换一个起始日期,日历月那一列会整列重算。
1 月 31 日加一个月为什么是 2 月 28 日,不是 3 月 3 日?
因为本页用的是月末夹取。setMonth() 的做法是把日期设成 2 月 31 日,JavaScript 发现这一天不存在就往后溢出,得到 3 月 3 日。本页改成先查 2 月有多少天(平年 28 天),再取「原日号 31」与「28」中的较小值,得到 2 月 28 日。两种做法都能自圆其说,但「3 月 1 日之后只过了一个月却跳到 3 月 3 日」会让多数人意外,所以这里选了夹取。闰年时结果是 2 月 29 日。
30 天制月和公历平均月差多少?什么时候该用哪个?
每差 30.436875 − 30 = 0.436875 天。短期看微不足道,长期会积累:100 天差 1.46 天,1000 天差 14.6 天,100 万天差 479.449 个月约 39.9 年。债券应计利息、银行贷款计息日、部分财务报表按 30/360 惯例用 30 天制月;排期、纪念日、合同自然月用日历月。两者不要混用在同一条计算链里。
朔望月 29.530588853 天和公历的「月」有什么关系?
没有直接关系,它是天文量而不是历法量。朔望月是月相重复一次的周期,精确值是 29 天 12 小时 44 分 3 秒左右,与公历月份长度无关,也不等于农历月(农历月按朔望月定,但通过置闰把一年的平均长度拉回回归年)。本页把它列出来,是想说明「月」至少有三种互不相等的定义,混用会出错。真正的农历换算要用「农历公历转换」那一页。
为什么 1 个月不是 4 周,而是 4.3481 周?
因为 4 周只有 28 天,而一个公历平均月是 30.436875 天。按 4 周算一个月,一年就只有 48 周 = 336 天,比真实的一年少了约 29 天。正确的换算系数是 30.436875 ÷ 7 = 4.3481;反过来说,一年是 365.2425 ÷ 7 = 52.1775 周,也是拿 52 周近似会亏掉一天多的地方。
输入 100 万天会算出什么?会不会溢出?
不会溢出。100 万天等于 33333.333 个 30 天制月,或从 2026-03-01 起 32854 个月 26 天,落点日期是 4764-01-27,仍在 Date 的表示范围内(上限约 ±1 亿天)。真要说风险,是这一行的日历月计算需要循环三万余次,在很老的设备上会有几十毫秒的延迟。上限就设在这里,输入更大的数字会被直接拒绝。
为什么「周 + 天」和「周(小数)」要同时给?
两个用途不同。「14 周 2 天」适合排期和口头表达,不会因为四舍五入产生歧义;「14.2857 周」适合继续参与乘法运算,比如按每周工时算总工时。用整数周去做乘法会丢精度:14 周 2 天如果当成 14 周,84 小时的一周工时下会少算 12 小时。算钱、算工时、算产能时用小数周,写文档、排进度时用整数周加余天。
相关工具
- 日期间隔天数计算器:给两个日期算出中间差多少天,与本页反着用正好互补——它给天数,本页把天数换成周、月、年。
- 日期加天数计算器:专门做「某天往后推 N 天」,本页的「落点日期」卡片用的是同一套日差算法。
- 天月计算器:查某个日历月到底有 28、29、30 还是 31 天,用来核对本页日历月那一列的进位点。
- 周日期计算器:按周为单位算两个日期之间隔了几周,比本页的「周(小数)」更适合排周计划。
- 周数字计算器:给出某个日期属于 ISO 8601 的第几周,跨年周的归属就靠它判断。
- 闰年判断工具:确认某一年是闰年还是平年,直接影响本页 2 月是 28 天还是 29 天。
- 工作日计算器:排除周末与节假日后再算天数,本页算的是自然日,两者常一起用。
- 日期时间:查看全部日期时间工具。