JS实现获取指定月份日历周数的函数(符合德国ISO周标准)
适配德国ISO 8601日历周规则的JS函数实现
德国通用的日历周遵循ISO 8601标准,规则如下:
- 每周以周一作为第一天,周日作为最后一天
- 每年的第一个日历周为包含当年1月4日的周(等价于包含当年第一个周四的周)
问题说明
你提供的原有代码核心问题是默认以周日为周起始,且未处理ISO周的跨年统计逻辑,因此不符合德国本地规范,也存在周数统计上限的问题。
实现代码
// 辅助函数:获取日期对应的ISO周信息(返回所属ISO年份、周数、当周周一、当周周日的日期对象) function getISOWeekInfo(date) { const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())); const dayOfWeek = d.getUTCDay() || 7; // 把周日的返回值从0转为7,匹配ISO周1-7的规则 // 计算当前周的周一日期 const weekStart = new Date(d); weekStart.setUTCDate(d.getUTCDate() - (dayOfWeek - 1)); // 计算当前周的周日日期 const weekEnd = new Date(weekStart); weekEnd.setUTCDate(weekStart.getUTCDate() + 6); // 计算周数 d.setUTCDate(d.getUTCDate() + 4 - dayOfWeek); const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1)); const weekNo = Math.ceil((((d - yearStart) / 86400000) + 1) / 7); return { year: d.getUTCFullYear(), week: weekNo, start: new Date(weekStart.getUTCFullYear(), weekStart.getUTCMonth(), weekStart.getUTCDate()), end: new Date(weekEnd.getUTCFullYear(), weekEnd.getUTCMonth(), weekEnd.getUTCDate()) }; } // 辅助函数:获取指定年份的ISO周总数量 function getISOWeeksInYear(year) { const lastDay = new Date(Date.UTC(year, 11, 31)); const lastWeekInfo = getISOWeekInfo(lastDay); return lastWeekInfo.week === 1 ? 52 : lastWeekInfo.week; } // 主函数:传入4位年份、1-12的月份,返回当月包含的日历周数 function getcalweeks(year, month) { const jsMonth = month - 1; // 转为JS Date的0-based月份规则 const monthFirstDay = new Date(year, jsMonth, 1); const monthLastDay = new Date(year, jsMonth + 1, 0); const firstWeek = getISOWeekInfo(monthFirstDay); const lastWeek = getISOWeekInfo(monthLastDay); // 规则1:只要周内有任意一天在当月就算入统计,取消下面注释即可启用 // if (firstWeek.year === lastWeek.year) { // return lastWeek.week - firstWeek.week + 1; // } // if (lastWeek.year > firstWeek.year) { // return (getISOWeeksInYear(firstWeek.year) - firstWeek.week + 1) + lastWeek.week; // } // return (getISOWeeksInYear(lastWeek.year) - firstWeek.week + 1) + lastWeek.week; // 规则2:仅统计完全属于当月的周(默认启用,匹配你给出的getcalweeks(2021,1)返回4的示例) let count = 0; let currentWeek = firstWeek; while (true) { if (currentWeek.start >= monthFirstDay && currentWeek.end <= monthLastDay) { count++; } const nextWeekFirstDay = new Date(currentWeek.start); nextWeekFirstDay.setDate(nextWeekFirstDay.getDate() + 7); if (nextWeekFirstDay > monthLastDay) break; currentWeek = getISOWeekInfo(nextWeekFirstDay); } return count; }
验证说明
getcalweeks(2021, 1)返回4,完全匹配你给出的示例预期- 支持所有年份的52/53周规则,不存在统计上限问题
- 完全适配德国本地日历周规范
内容的提问来源于stack exchange,提问作者silliton
相关产品推荐
相关产品推荐

