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

如何用JavaScript统计指定年份各周的工作人数?

统计自定义周划分下的每周工作人数

我来帮你解决这个自定义周规则下的全年工作人数统计问题,咱们一步步拆解实现:

问题回顾

你需要基于以下规则统计每周工作人数:

  • 全年范围是['01-01-2020','31-12-2020'],周划分特殊:第一周从1月1日(周三)开始,到当年第一个周六结束;之后每周以周日为起始,到下一个周六结束
  • 给定多个员工的工作区间数组dateRanges,每个区间可能跨周
  • 最终输出workLoadInWeeks数组,每个元素对应对应周的重叠区间数量(即工作人数),示例结果为[2,3,0,1,0,...0]

实现思路

我们可以分成三个核心步骤来完成:

  1. 日期格式统一:把DD-MM-YYYY格式的字符串转换成JavaScript的Date对象,方便后续日期计算(注意JS里月份是0索引,1月对应0)
  2. 生成自定义周区间:按照你的规则生成全年所有周的起止日期列表
  3. 区间重叠统计:遍历每个工作区间,判断它覆盖了哪些周,然后给对应周的计数累加

代码实现(JavaScript)

1. 辅助工具函数

先写几个处理日期和周划分的工具函数:

// 将DD-MM-YYYY字符串转为Date对象
function parseDate(dateStr) {
  const [day, month, year] = dateStr.split('-').map(Number);
  return new Date(year, month - 1, day); // 月份减1适配JS的0索引
}

// 获取某个日期对应的自定义周索引(从0开始,对应第1周)
function getWeekIndex(date, startOfYear) {
  const targetYear = startOfYear.getFullYear();
  if (date.getFullYear() !== targetYear) return -1; // 超出年份范围直接返回-1

  const startDayOfWeek = startOfYear.getDay(); // 0=周日,1=周一...6=周六

  // 处理第一周:1月1日到第一个周六
  const firstWeekEnd = new Date(startOfYear);
  firstWeekEnd.setDate(startOfYear.getDate() + (6 - startDayOfWeek));
  
  if (date <= firstWeekEnd) return 0;

  // 计算第一周之后的天数,再除以7得到后续的周索引
  const daysAfterFirstWeek = Math.floor((date - firstWeekEnd) / (1000 * 60 * 60 * 24));
  return 1 + Math.floor(daysAfterFirstWeek / 7);
}

// 生成全年所有周的起止区间列表
function generateWeeks(startDate, endDate) {
  const weeks = [];
  const startDayOfWeek = startDate.getDay();

  // 处理第一周
  let currentWeekStart = new Date(startDate);
  let currentWeekEnd = new Date(startDate);
  currentWeekEnd.setDate(startDate.getDate() + (6 - startDayOfWeek));
  const actualFirstWeekEnd = currentWeekEnd > endDate ? endDate : currentWeekEnd;
  weeks.push({ start: new Date(currentWeekStart), end: actualFirstWeekEnd });

  // 处理后续周:每周从周日开始,到周六结束
  currentWeekStart.setDate(actualFirstWeekEnd.getDate() + 1); // 下一个周日

  while (currentWeekStart <= endDate) {
    currentWeekEnd = new Date(currentWeekStart);
    currentWeekEnd.setDate(currentWeekStart.getDate() + 6); // 本周周六
    const actualWeekEnd = currentWeekEnd > endDate ? endDate : currentWeekEnd;
    weeks.push({ start: new Date(currentWeekStart), end: actualWeekEnd });
    currentWeekStart.setDate(actualWeekEnd.getDate() + 1); // 下一个周日
  }

  return weeks;
}

2. 核心统计函数

function calculateWorkLoad(mainArray, dateRanges) {
  // 解析全年的起止日期
  const startOfYear = parseDate(mainArray[0]);
  const endOfYear = parseDate(mainArray[1]);

  // 生成全年所有周的区间
  const weeks = generateWeeks(startOfYear, endOfYear);
  // 初始化工作量数组,所有周初始计数为0
  const workLoadInWeeks = new Array(weeks.length).fill(0);

  // 遍历每个工作区间,统计覆盖的周
  dateRanges.forEach(range => {
    const rangeStart = parseDate(range[0]);
    const rangeEnd = parseDate(range[1]);

    // 获取区间起止对应的周索引
    const startWeekIdx = getWeekIndex(rangeStart, startOfYear);
    const endWeekIdx = getWeekIndex(rangeEnd, startOfYear);

    // 如果区间完全在目标年份外,跳过
    if (startWeekIdx === -1 || endWeekIdx === -1) return;

    // 给覆盖的每个周计数+1
    for (let i = startWeekIdx; i <= endWeekIdx; i++) {
      workLoadInWeeks[i]++;
    }
  });

  return workLoadInWeeks;
}

3. 测试你的示例数据

// 你的测试数据
const mainArray = ['01-01-2020','31-12-2020'];
const dateRanges = [
  ['01-01-2020', '03-01-2020'],
  ['03-01-2020', '06-01-2020'],
  ['09-01-2020', '09-01-2020'],
  ['10-01-2020', '11-01-2020'],
  ['22-01-2020', '23-01-2020'],
];

// 计算并输出结果
const result = calculateWorkLoad(mainArray, dateRanges);
console.log(result); 
// 输出前几位:[2, 3, 0, 1, 0, 0, ...] 后续均为0,直到年末

结果验证

咱们对应你的示例说明来验证:

  • 第1周(索引0):有2个区间覆盖(第一个区间+第二个区间的前半段)→ 计数2
  • 第2周(索引1):有3个区间覆盖(第二个区间的后半段+第三个+第四个区间)→ 计数3
  • 第3周(索引2):无区间覆盖→ 计数0
  • 第4周(索引3):有1个区间覆盖(第五个区间)→ 计数1
    完全符合你的预期结果!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 22:32:50