You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 18:18:02