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

JavaScript实现:计算数组中指定日期倒推的连续天数

问题:计算从指定日期倒推的连续天数函数

需要编写一个函数,接收可能未排序的日期数组(date_array)作为输入,计算从指定日期(start_date)倒推的连续天数(不包含start_date本身)。

示例:
start_date = 23.01.2023

date_array = [
01.01.2023,
02.01.2023,
20.01.2023, <- 连续天数第3天
21.01.2023, <- 连续天数第2天
22.01.2023, <- 连续天数第1天
22.01.2023, <- 连续天数第1天
23.01.2023,
24.01.2023]

结果:
streak_length: 3 days

我原本的思路是从start_date倒推创建日期范围,统计数组中处于该范围内的日期数量,每次循环将范围结束日期再往前推一天,直到统计数量不再增长。但现在遇到了start_date在循环前被end_date覆盖的问题,希望得到问题解决方法或更优实现方案。

现有代码如下:

const dateArray = [
  new Date("2022-12-31"), 
  new Date("2023-01-02"), // 连续天数第3天
  new Date("2023-01-03"), // 连续天数第2天 
  new Date("2023-01-03"), // 连续天数第2天
  new Date("2023-01-04"), // 连续天数第1天
  new Date("2023-01-05")];

const d_start = new Date("2023-01-05");

function currentStreak(dateArray, d_start) {
    // dateArray: 事件发生日期的数组
    // d_start: 连续天数的起始日期,不包含在内

    // 创建范围 d_start ... d_end,d_end初始为d_start前一天
    let d_end = d_start
    d_end.setDate(d_start.getDate() - 1)
    let countPrev = -1
    let count = 0
    let streakCount = 0

    // 统计数组中在范围内的元素数量,直到数量不再增长时停止循环
    while (count > countPrev) {
        countPrev = count
        // 统计数组中在start和end日期之间的元素数量
        count = dateArray.reduce((accumulator, currentValue) => {
          if((d_start > currentValue) && (currentValue > d_end))
          {
            accumulator += 1
          }
         return accumulator
        }, 0)
        // 设置下一次迭代的新结束日期
        d_end = d_end.setDate(d_end.getDate() - 1)
        streakCount = streakCount+1
    }
    return count;
  }

currentStreak(dateArray, d_start)

问题分析与解决方案

当前代码的核心问题

  1. Date对象引用覆盖:let d_end = d_start是直接赋值引用,不是创建新日期对象,调用d_end.setDate()会直接修改原d_start的值,这就是start_date被覆盖的原因。
  2. 逻辑方向错误:连续天数只需要判断某一天是否存在记录,不需要统计当天的记录数量,原代码的统计逻辑会导致误判。
  3. 类型转换错误:d_end = d_end.setDate(...)会把Date对象转为时间戳数字,后续调用getDate()会直接报错。

修复后的实现代码

const dateArray = [
  new Date("2022-12-31"), 
  new Date("2023-01-02"),
  new Date("2023-01-03"),
  new Date("2023-01-03"),
  new Date("2023-01-04"),
  new Date("2023-01-05")];

const d_start = new Date("2023-01-05");

function currentStreak(dateArray, d_start) {
    // 标准化日期:去除时分秒干扰,转为时间戳存入Set,实现O(1)查询
    const dateSet = new Set(dateArray.map(date => {
        const normalized = new Date(date);
        normalized.setHours(0, 0, 0, 0);
        return normalized.getTime();
    }));

    let streakCount = 0;
    const checkDate = new Date(d_start);
    // 从start_date的前一天开始检查
    checkDate.setDate(checkDate.getDate() - 1);

    // 倒推检查每一天是否存在记录
    while (true) {
        const checkTimestamp = checkDate.setHours(0, 0, 0, 0);
        if (dateSet.has(checkTimestamp)) {
            streakCount++;
            checkDate.setDate(checkDate.getDate() - 1);
        } else {
            // 遇到无记录的日期,终止循环
            break;
        }
    }

    return streakCount;
}

console.log(currentStreak(dateArray, d_start)); // 输出:3

更优思路说明

  1. 日期标准化:把所有日期的时分秒重置为0,避免不同时间点的同一日期被误判,同时用Set存储时间戳,查询效率远高于遍历数组。
  2. 直接倒推检查:从目标日期前一天开始,每天往前推,只要当天存在记录就计数,直到遇到空日期为止,逻辑简单且高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 05:10:55