You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将星期数字数组转换为可跨周的日期名称范围?

我来帮你解决这个问题!你的核心痛点是处理跨周连续的日期块(比如周五、周六、周日、周一要合并成"Friday-Monday"),同时简化代码逻辑。咱们一步一步来:

首先,先明确原代码的问题:

  • 没考虑「6(周六)之后接0(周日)属于连续」的情况
  • 也没处理首尾区间跨周合并的场景
  • 字符串拼接的逻辑过于繁琐,可读性差

解决方案思路

  1. 预处理输入:先对输入数组去重、排序,避免乱序或重复值干扰逻辑
  2. 生成连续区间:遍历排序后的数组,把连续的日期(包括6→0的跨周连续)归为同一个区间
  3. 跨周区间合并:如果首尾两个区间是跨周连续的(比如最后一个区间是[5,6],第一个是[0,1]),就把它们合并成一个跨周区间
  4. 转换为友好字符串:把每个区间转换成「单个日期」或「起始-结束日期」的格式

完整实现代码

const dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];

function formatDays(days) {
  // 1. 去重并排序,确保日期按顺序排列
  const sortedDays = [...new Set(days)].sort((a, b) => a - b);
  if (sortedDays.length === 0) return [];

  // 2. 生成连续日期区间
  const intervals = [];
  let [currentStart, currentEnd] = [sortedDays[0], sortedDays[0]];

  for (let i = 1; i < sortedDays.length; i++) {
    const currentDay = sortedDays[i];
    const prevDay = sortedDays[i - 1];
    
    // 判断是否连续:要么是前一天+1,要么是周六(6)接周日(0)
    if (currentDay === prevDay + 1 || (prevDay === 6 && currentDay === 0)) {
      currentEnd = currentDay;
    } else {
      // 不连续则保存当前区间,开始新的区间
      intervals.push([currentStart, currentEnd]);
      [currentStart, currentEnd] = [currentDay, currentDay];
    }
  }
  // 保存最后一个区间
  intervals.push([currentStart, currentEnd]);

  // 3. 处理跨周合并:如果首尾区间是跨周连续的
  if (intervals.length > 1) {
    const firstInterval = intervals[0];
    const lastInterval = intervals.at(-1);
    // 检查最后一个区间的结束日+1 是否等于第一个区间的起始日(模7处理跨周)
    if ((lastInterval[1] + 1) % 7 === firstInterval[0]) {
      // 合并首尾区间
      const mergedInterval = [lastInterval[0], firstInterval[1]];
      intervals.pop();
      intervals.shift();
      intervals.unshift(mergedInterval);
    }
  }

  // 4. 转换为目标字符串格式
  return intervals.map(([start, end]) => {
    if (start === end) return dayNames[start];
    return `${dayNames[start]}-${dayNames[end]}`;
  });
}

// 测试你的例子
console.log(formatDays([0,1,2,4,5])); // ["Sunday-Tuesday", "Thursday-Friday"]
console.log(formatDays([0,1,3,5,6])); // ["Friday-Monday", "Wednesday"]

代码解释

  • 预处理步骤:用Set去重,再排序,保证后续逻辑只处理有序且唯一的日期值
  • 区间生成:通过遍历判断当前日期是否和前一个连续,连续则扩展当前区间,否则保存当前区间并开启新的
  • 跨周合并:通过(lastInterval[1] + 1) % 7 === firstInterval[0]判断首尾是否跨周连续,是的话合并成一个区间
  • 字符串转换:单个日期直接返回名称,区间则返回「起始-结束」的格式,跨周的情况(比如start=5,end=1)会自动生成"Friday-Monday",完全符合你的需求

对比原代码的优势

  • 逻辑更清晰:用区间的方式处理连续日期,避免了繁琐的字符串拼接和切割
  • 完美支持跨周场景:专门处理了6→0的连续情况,以及首尾区间的跨周合并
  • 代码更简洁:去掉了冗余的字符串操作,用数组和区间的思路简化逻辑

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

火山引擎 最新活动