使用方法
- 打开周日期计算器时开始日期已预置 2026-01-01、结束日期已预置 2026-03-26,结果区直接给出 ISO 周日期 2026-W01-4 与区间 12 整周,无需任何配置。
- 想查某一天属于第几周,把「开始日期」改成目标日期即可;结果区会同时给出该日的 ISO 周年、周编号、星期几、距本周周一的天数。
- 想统计跨度,把「结束日期」也设好:结果区给出整日差、完整周数与剩余天数,例如默认组合是 84 天 = 12 整周 + 0 天。
- 点「复制结果」把整块文字(含周编号与区间统计)送进剪贴板;键盘上按 Enter(单行日期框)即可触发计算。
- 下方对照表列出跨年边界日期,默认 12 行,可「加载更多」展开,或「导出对照表 CSV」(带 BOM)/「复制对照表」(TSV)。
这个周日期计算器能解决什么问题
第一类场景是对齐项目周期。很多团队按「第几周」排计划,但同一句「2026 年第 1 周」在公历口径和 ISO 口径下可能指向完全不同的七天;本页用 ISO 8601 定义把日期钉到具体的周编号,避免周会开在错误的那一周。
第二类场景是财务与人事的周结口径。工资周、排班周、周报周常需要「本周一到本周日」的边界,而 1 月 1 日、12 月 31 日恰好卡在跨年位置时最容易算错;本页把这些边界日期列成对照表,一眼能看出哪几天属于上一年。
第三类场景是数据对账。日志、导出报表常带 ISO 周编号(strftime 的 %G / %V),拿本页换算公历日期,可以快速定位「2026-W53」到底是哪几天,也能确认某年到底有没有第 53 周。
本页只做 ISO 周编号与区间周数:只要两个日期相差多少天走 日期间隔天数计算器,只要某天的公历星期走 天周计算器,只要排除周末的工作日走 工作日计算器。本页不算农历、不算节假日调休,也不做时区换算。
原理与规则说明
算法用 ISO 8601 的周四规则:先把日期移到它所在 ISO 周的周四,再数这一年从 1 月 1 日起有多少个七天。实现上是先算星期(周一 = 1 … 周日 = 7,JS 的 getDay() 返回 0 表示周日所以要 day || 7),再把日期整体平移 4 - day 天落到本周周四,最后用 Math.ceil(((周四 - 当年 1 月 1 日) / 86400000 + 1) / 7) 得到周编号,周四所在的年份就是 ISO 周年。默认例子 2026-01-01 是周四,平移量为 0,得到 ISO 周日期 2026-W01-4。
为什么用周四而不是周一或周三:ISO 8601 规定第 1 周是「包含当年第一个周四的那一周」,等价于「包含 1 月 4 日的那一周」,也等价于「至少有 4 天落在本年的第一周」。用周四定位的好处是:一周里只有周四的年份归属必然等于该周的多数天数归属,所以「这一周属于哪一年」有唯一答案。若用周三定位,就会和「至少 4 天」的规则打架。
于是 1 月 1 日不一定是第 1 周。当 1 月 1 日落在周五、周六、周日时,它属于上一年最后一周(第 52 或 53 周)。对照表里 2025-12-31(周三)已经是 2026-W01-3,而 2027-01-01(周五)仍属 2026-W53-5,就是这个规则的表现。反过来,12 月 29 日之后也可能已经进入下一年的第 1 周,例如 2024-12-30 属于 2025-W01-1。
一年有 52 周还是 53 周可以判定:某 ISO 年长度 53 周,当且仅当该年 1 月 1 日是周四,或它是闰年且 1 月 1 日是周三。实测:2020(闰年,1 月 1 日周三)与 2026(1 月 1 日周四)都是 53 周,2019、2021、2024、2025、2027 都是 52 周。判定方法很简单——取该年 12 月 28 日(它必然落在当年最后一周)算一次周编号即可,本页结果区就用这个办法报出「共 53 周」。
为什么不用 Intl.DateTimeFormat 的周编号:实测 new Intl.DateTimeFormat('en-US', { week: 'numeric' }) 输出的仍是日期(如 1/1/2026),因为 week 并不是该 API 的标准选项,传了会被忽略——它没有周编号能力。真正带区域周信息的是 Intl.Locale.prototype.weekInfo:zh-CN 得到 { firstDay: 1, minimalDays: 1 }、en-US 是 { firstDay: 7, minimalDays: 1 }、de-DE 才是 { firstDay: 1, minimalDays: 4 }。ISO 要求一周至少有 4 天落在本年(即 minimalDays = 4),只有像 de-DE 这类区域与 ISO 一致;zh-CN 虽然 firstDay 也是周一,但 minimalDays 是 1,所以按它算出的「本地第几周」与 ISO 周编号并不相同。这就是本页必须自己实现 ISO 周、而不能直接调 Intl 的原因。
区间周数的口径:本页按 UTC 整日差算——Math.round((结束 - 开始) / 86400000),把开始与结束都落在当天 00:00,所以「相差几个完整周」= 整日差整除 7,余数单列为天数。这样 2026-01-01 到 2026-03-26 是 84 天 = 12 整周 + 0 天,而不是含糊的「约 12 周」。相邻两天算 1 天、同一天算 0 天。
完整示例(数值仅作演示)
取周日期计算器的默认值开始日期 2026-01-01、结束日期 2026-03-26:
- ISO 周日期:2026-01-01 是周四,落在 ISO 2026 年第 1 周的第 4 天 →
2026-W01-4。 - 年内位置:公历 2026 年第 1 天;该周周一 2025-12-29、周日 2026-01-04,2026-01-01 距周一 3 天。
- 年度长度:ISO 2026 共 53 周(1 月 1 日为周四);相邻的 ISO 2025 与 ISO 2027 各 52 周。
- 区间统计:84 天 = 12 整周 + 0 天,两端 ISO 周日期从 2026-W01-4 到 2026-W13-4。
- 边界提醒:同样的「第 1 周」在 2025-12-29(周一)就已开始,比公历 2026 年早了 3 天。
上面每个数字都与结果区首次计算一致,也与对照表第 4 行(2026-01-01 → 2026-W01-4)和第 12 行(2026-03-26 → 2026-W13-4)逐位一致,可复制结果复核。
输入范围与对照表
两个日期都限定在 1900-01-01 至 2100-12-31(type="date" 自带日历选择器),空值、格式不对、以及 2026-02-30 这类不存在的日期都会给出具体中文提示。下面这张表列出跨年边界日期,默认 12 行:
| 日期 | ISO 周日期 | 公历星期 | 边界说明 |
|---|---|---|---|
| 2025-12-28 | 2025-W52-7 | 周日 | 2025 年最后一周 |
| 2025-12-29 | 2026-W01-1 | 周一 | 已进入 ISO 2026 第 1 周 |
| 2025-12-31 | 2026-W01-3 | 周三 | 公历还在 2025,ISO 已是 2026 |
| 2026-01-01 | 2026-W01-4 | 周四 | 当年第一个周四所在周 |
| 2026-01-04 | 2026-W01-7 | 周日 | 第 1 周的周日 |
| 2026-01-05 | 2026-W02-1 | 周一 | 第 2 周从周一开始 |
| 2026-12-31 | 2026-W53-4 | 周四 | 2026 年有第 53 周 |
| 2027-01-01 | 2026-W53-5 | 周五 | 公历已 2027,ISO 仍属 2026 |
| 2020-12-31 | 2020-W53-4 | 周四 | 2020 年也是 53 周 |
| 2021-01-01 | 2020-W53-5 | 周五 | 属 ISO 2020 第 53 周 |
| 2024-12-30 | 2025-W01-1 | 周一 | 已进入 ISO 2025 第 1 周 |
| 2026-03-26 | 2026-W13-4 | 周四 | 与默认区间终点一致 |
输入范围、边界与精度说明
ISO 周年可能不等于公历年,这是最容易被忽略的一条。当 ISO 周年与公历年不同,结果区会分别标出:2025-12-31 的公历年是 2025、ISO 周年是 2026;2027-01-01 的公历年是 2027、ISO 周年是 2026。做周编号对账时,务必用 ISO 周年而不是公历年去拼 YYYY-Www,否则会差整整一年。
1 月 1 日属于第 1 周的三种情形:若 1 月 1 日是周一至周四,它是第 1 周(周四规则下必属当年);若是周五、周六、周日,它就属于上一年最后一周。实测 2021、2022、2023、2027、2028 年的 1 月 1 日都不在第 1 周,全部落在上一年的第 52 或 53 周,对照表里能逐条核对。
53 周年份的判定与分布:某 ISO 年有 53 周,当且仅当该年 1 月 1 日是周四,或该年为闰年且 1 月 1 日是周三。近年的 53 周年份有 2020、2026、2032,其余多为 52 周。ISO 8601 还规定 12 月 28 日永远落在当年的最后一周,本页就是用它读出年度周数,所以你看到的「共 53 周」不会是估计值。
日差用 UTC 整日。把两个日期都按 UTC 00:00 处理再相减,可以避免夏令时与本地时区带来的 23 小时 / 25 小时误差——用本地时间直接相减,在某些时区的夏令时切换日会算出 0.958 天这类小数,四舍五入后就可能差一天。本页统一走 UTC,跨时区结果一致。
区间方向必须正确。结束日期早于开始日期会被拦下并明确提示交换两个日期,而不是悄悄取绝对值——静默取绝对值会让你在写报表公式时以为方向对了。同一天算 0 整周 0 天,是合法输入。
不做的事:本页不处理本地化周起始日(某些地区一周从周日开始)、不处理财政周(很多企业以 4-4-5 或 13 周为一季)、不算农历与节假日。这些口径都需要显式配置,本页只给 ISO 8601 这一套标准答案。
常见问题
为什么 2026-01-01 是第 1 周,而 2025-12-29 也已经是第 1 周?
因为 ISO 8601 的周从周一开始、第 1 周是含当年第一个周四的那一周。2026 年第一个周四是 2026-01-01,它所在的那一周从 2025-12-29(周一)起算,所以 2025-12-29 到 2026-01-04 都属于 2026 年第 1 周。公历年与 ISO 周年在跨年处会错开几天,属正常现象。
2026 年真的有第 53 周吗?
有。判定规则是「1 月 1 日是周四,或闰年且 1 月 1 日是周三」,2026-01-01 正好是周四,所以 ISO 2026 有 53 周,2026-12-28 至 2027-01-03 属于第 53 周。2027-01-01 虽然是公历新年,ISO 上仍属 2026-W53。
Intl.DateTimeFormat 能直接给我周编号吗?
不能。实测 new Intl.DateTimeFormat('en-US', { week: 'numeric' }) 输出的还是日期文本,因为 week 不是它的标准选项,会被忽略。稍接近的是 Intl.Locale(...).weekInfo,它给出 firstDay 与 minimalDays,但那是区域偏好而非固定 ISO 规则,所以本页自己实现周四算法。
zh-CN 的周信息为什么和 ISO 不一样?
实测 Intl.Locale('zh-CN').weekInfo 是 { firstDay: 1, minimalDays: 1 },而 de-DE 是 { firstDay: 1, minimalDays: 4 }。ISO 要求 minimalDays 为 4,所以只有 de-DE 这类区域与 ISO 一致;zh-CN 的 minimalDays 为 1,按它算的周编号会与 ISO 不同,不能混用。
两个日期的「相差几周」为什么不是简单相减天数除以 7?
本页就是天数除以 7,但把余数单独列出:84 天报「12 整周 + 0 天」而不是「约 12 周」。这样你在做排期时知道还多出几天零头。若要的是自然周计数(跨了几周而不是相差几个七天),那属于另一种口径,本页不提供,避免两种结果混淆。
区间结果会受时区或夏令时影响吗?
不会。本页把两个日期都按 UTC 00:00 对齐再相减,避免本地夏令时切换日出现 23 小时或 25 小时的偏差。所以你在任何时区打开本页,同一天的周编号与同两个日期的日差结果都一样。
为什么结束日期早于开始日期会报错,而不是自动交换?
这是刻意的:静默交换会把「方向填反」这个错误藏起来,你在核对报表公式时会误以为顺序对了。本页直接提示两个日期并建议交换,让你明确知道输入有问题。需要反向着算,手动换一下两个框即可。