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

如何用JavaScript获取两个日期间每月第N个周几的日期实现重复日程

解决方案

核心思路

首先从起始日程中提取两个重复规则参数:

  • targetWeekday:目标周几,对应JS Date.getDay()的返回值(0=周日,1=周一,...6=周六)
  • weekOrder:目标是当月的第几个周几,支持1/2/3/4代表前四个,-1代表最后一个
    之后遍历起止日期范围内的每一个月份,对每个月计算符合规则的日期,落在时间范围内的就加入展示列表即可。

核心工具函数

先实现一个通用的「按规则取月度周几日期」函数,逻辑清晰易修改:

/**
 * 计算指定年月的第N个周几的日期
 * @param {number} year 年份 例:2024
 * @param {number} month 月份(0基,和JS Date对齐) 例:3代表4月
 * @param {number} targetWeekday 目标周几 0=周日 1=周一...6=周六
 * @param {number} weekOrder 第几个 1=第一个 2=第二个...-1=最后一个
 * @returns {Date|null} 符合条件的日期,不存在则返回null
 */
function getMonthWeekdayDate(year, month, targetWeekday, weekOrder) {
  if (weekOrder === -1) {
    // 算最后一个周几的逻辑:先拿当月最后一天
    const lastDayOfMonth = new Date(year, month + 1, 0);
    const lastDayWeekday = lastDayOfMonth.getDay();
    // 计算需要往前减的天数
    const diff = (lastDayWeekday - targetWeekday + 7) % 7;
    lastDayOfMonth.setDate(lastDayOfMonth.getDate() - diff);
    return lastDayOfMonth;
  }
  // 算第N个周几的逻辑:先拿当月第一天
  const firstDayOfMonth = new Date(year, month, 1);
  const firstDayWeekday = firstDayOfMonth.getDay();
  // 计算第一个目标周几需要加的天数
  let addDays = (targetWeekday - firstDayWeekday + 7) % 7;
  // 加上第N个的偏移
  addDays += (weekOrder - 1) * 7;
  const result = new Date(year, month, 1 + addDays);
  // 校验算出来的日期是不是还在当月,避免第5个周几不存在的情况
  if (result.getMonth() !== month) return null;
  return result;
}

整合到原有代码

在你原来的if (jsonArray[num].tipoRepeticion == "2")代码块中加入以下逻辑即可:

if (jsonArray[num].tipoRepeticion == "2") {
  // 1. 从起始日期提取重复规则
  const targetWeekday = starDate.getDay();
  // 计算起始日期是当月的第几个周几
  const startDateDay = starDate.getDate();
  const weekOrder = Math.ceil(startDateDay / 7);
  // 补充:如果你的需求支持用户手动选最后一个,这里weekOrder可以改成从用户配置取-1即可

  // 2. 遍历起止范围内的每一个月
  let currentYear = starDate.getFullYear();
  let currentMonth = starDate.getMonth();
  const endYear = endDate.getFullYear();
  const endMonth = endDate.getMonth();

  while (currentYear < endYear || (currentYear === endYear && currentMonth <= endMonth)) {
    // 计算当前月符合规则的日期
    const currentEventDate = getMonthWeekdayDate(currentYear, currentMonth, targetWeekday, weekOrder);
    // 校验日期有效、且在起止日期范围内
    if (currentEventDate && currentEventDate >= starDate && currentEventDate <= endDate) {
      // 沿用你原来的格式化和入队逻辑
      const str = ((currentEventDate.getMonth()+1) + "/" + currentEventDate.getDate() + "/" + currentEventDate.getFullYear()).toString();
      eventMen.push({
        date: constructDates(str, 0, jsonArray[num].tipoRepeticion),
        title: jsonArray[num].titulo,
        descripcion: jsonArray[num].descripcion,
        tipo: jsonArray[num].tipo,
        tipoRepeticion : jsonArray[num].tipoRepeticion
      });
    }
    // 跳到下一个月
    currentMonth++;
    if (currentMonth > 11) {
      currentMonth = 0;
      currentYear++;
    }
  }
}

注意点

  • 如果需要支持用户手动选择「最后一个周几」的规则,只需要把代码中weekOrder的取值改成从你保存用户配置的字段取-1即可,工具函数已经兼容该逻辑
  • 代码自动过滤了不存在的第5个周几的情况(比如某个月只有4个周三,就不会生成无效日期)
  • 遍历月份的逻辑比你原来遍历所有天数的性能更高,尤其是日程跨度好几年的场景优势更明显

内容的提问来源于stack exchange,提问作者Claudio César Pérez Velasco

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 22:15:00