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

JavaScript根据日期范围生成月度周数据:代码输出错误排查

月度周号数组生成代码修正

需求描述

输入一组起止日期,需生成包含月度周号、周开始日期、周结束日期的数组。

输入示例

startDate = "2022-10-21"
endDate = "2022-12-05"

期望输出示例

result = [
  {weekNo: "Oct 2022 - Week 4", weekStartDate: "2022-10-21", weekEndDate: "2022-10-23"},
  {weekNo: "Oct 2022 - Week 5", weekStartDate: "2022-10-24", weekEndDate: "2022-10-30"},
  {weekNo: "Oct 2022 - Week 6", weekStartDate: "2022-10-31", weekEndDate: "2022-10-31"},
  {weekNo: "Nov 2022 - Week 1", weekStartDate: "2022-11-01", weekEndDate: "2022-11-06"},
  {weekNo: "Nov 2022 - Week 2", weekStartDate: "2022-11-07", weekEndDate: "2022-11-13"},
  {weekNo: "Nov 2022 - Week 3", weekStartDate: "2022-11-14", weekEndDate: "2022-11-20"},
  {weekNo: "Nov 2022 - Week 4", weekStartDate: "2022-11-21", weekEndDate: "2022-11-27"},
  {weekNo: "Nov 2022 - Week 5", weekStartDate: "2022-11-28", weekEndDate: "2022-11-30"},
  {weekNo: "Dec 2022 - Week 1", weekStartDate: "2022-12-01", weekEndDate: "2022-12-04"},
  {weekNo: "Dec 2022 - Week 2", weekStartDate: "2022-12-05", weekEndDate: "2022-12-05"}
];

当前实现代码

constructWeekDataForCustomDates(startDate, endDate) {
      let currentDay = moment(startDate).day(), addDays, weekArrayData = [];

      if (currentDay == 0) {
        addDays = 1;
      }
      else if (currentDay == 1) {
        addDays = 0;
      }
      else if (currentDay == 2) {
        addDays = 6;
      }
      else if (currentDay == 3) {
        addDays = 5;
      }
      else if (currentDay == 4) {
        addDays = 4;
      }
      else if (currentDay == 5) {
        addDays = 3;
      }
      else if (currentDay == 6) {
        addDays = 2;
      }

      while(startDate <= endDate){
        weekArrayData.push({
          checkboxName: this.getweekNoOfMonth(startDate),
          checkboxStartValue: moment(startDate).format("YYYY-MM-DD"),
          checkboxEndValue: moment(startDate).add(addDays, 'day').format("YYYY-MM-DD")
        });

        startDate = moment(startDate).add(addDays, 'day').format("YYYY-MM-DD");
        addDays =  6;
      }
      console.log(weekArrayData)
    }
 // Function To get week no based on the date
 getweekNoOfMonth (date) {
    let input = moment(date)
    const firstDayOfMonth = input.clone().startOf('month');
    const firstDayOfWeek = firstDayOfMonth.clone().startOf('week');
  
    const offset = firstDayOfMonth.diff(firstDayOfWeek, 'days');
  
    return Math.ceil((input.date() + offset) / 7);
  }

问题排查

原代码存在以下核心问题:

  1. 周结束日期逻辑错误:原代码计算的是到下一个周一的天数,而非需求中的本周日(或边界日期)。例如2022-10-21(周五)会被计算到2022-10-24(周一),但期望是到2022-10-23(周日)。
  2. 周号格式不匹配:getweekNoOfMonth仅返回数字,未生成需求要求的"月 年 - Week 数字"格式字符串。
  3. 边界处理缺失:后续循环固定加6天,未考虑周结束日期超过当月最后一天或输入的endDate的情况,导致跨月时周数据错误(如10月31日会被错误合并到11月的周)。
  4. 日期比较风险:使用字符串字典序比较日期,跨月时会出现逻辑错误(如"2022-10-31" > "2022-11-01"字符串比较为true,但实际日期前者更小)。

修正后的代码

constructWeekDataForCustomDates(startDate, endDate) {
  // 转为moment对象,避免字符串比较错误
  const startMoment = moment(startDate);
  const endMoment = moment(endDate);
  const weekArrayData = [];

  let currentStart = startMoment.clone();

  while (currentStart.isSameOrBefore(endMoment)) {
    // 计算本周日的日期
    let currentEnd = currentStart.clone().endOf('week');
    // 取本周日、当月最后一天、结束日期的最小值作为周结束日期
    const monthEnd = currentStart.clone().endOf('month');
    currentEnd = moment.min(currentEnd, monthEnd, endMoment);

    // 生成符合格式的周号
    const weekNo = this.getFormattedWeekNo(currentStart);

    weekArrayData.push({
      weekNo: weekNo,
      weekStartDate: currentStart.format("YYYY-MM-DD"),
      weekEndDate: currentEnd.format("YYYY-MM-DD")
    });

    // 下一周起始为当前周结束日期+1天
    currentStart = currentEnd.clone().add(1, 'day');
  }

  console.log(weekArrayData);
  return weekArrayData;
}

// 生成格式化的月度周号字符串
getFormattedWeekNo(dateMoment) {
  const input = dateMoment.clone();
  const firstDayOfMonth = input.clone().startOf('month');
  const firstDayOfWeek = firstDayOfMonth.clone().startOf('week');
  
  const offset = firstDayOfMonth.diff(firstDayOfWeek, 'days');
  const weekNum = Math.ceil((input.date() + offset) / 7);
  
  // 返回"月缩写 年 - Week 数字"格式
  return `${input.format('MMM YYYY')} - Week ${weekNum}`;
}

修正说明

  1. 日期处理优化:全程使用moment对象操作和比较日期,避免字符串比较的逻辑错误。
  2. 周结束日期修正:通过endOf('week')获取本周日,再与当月最后一天、输入结束日期取最小值,确保周结束日期不超出边界。
  3. 周号格式修正:修改周号生成函数,返回需求要求的字符串格式,同时保留原正确的周数计算逻辑。
  4. 循环逻辑调整:每次循环从当前周结束日期的次日开始,直到超过输入的结束日期,确保所有日期区间都被覆盖。

内容的提问来源于stack exchange,提问作者Subha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 23:41:11