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

JavaScript实现24小时循环时段间隙时长计算方案咨询

24小时循环时段间隙计算逻辑优化

核心需求

计算24小时循环时间周期内所有时段间的间隙时长,重点覆盖最后一个时段终点到第一个时段起点跨零点的间隙场景。

测试场景

场景1

预期识别间隙:23:00 - 01:00,时段配置如下:

const b1 = {
    id: 1,
    start: '01:00',
    end: '06:00',
};
const b2 = {
    id: 2,
    start: '06:00',
    end: '17:00',
};
const b3 = {
    id: 3,
    start: '17:00',
    end: '23:00',
};

场景2

预期识别间隙:06:00 - 08:00,同时存在17:00 - 20:00、24:00 - 23:00两段时段重叠,时段配置如下:

const b1 = {
    id: 1,
    start: '23:00',
    end: '06:00',
};
const b2 = {
    id: 2,
    start: '08:00',
    end: '20:00',
};
const b3 = {
    id: 3,
    start: '17:00',
    end: '24:00',
};

原有代码缺陷

原有逻辑仅能按数组传入顺序识别相邻时段的间隙,无法处理跨零点、时段乱序、时段重叠场景,核心问题有两点:

  1. 未对时段做排序和重叠合并,直接按传入顺序判断相邻关系,场景适配性差
  2. 未对跨零点时间做偏移处理,无法识别结束时间数值小于下一个时段开始时间数值的跨零点间隙

原有代码如下:

const timeStringToNumber = (time24Hours) => {
    const hoursMinutes = time24Hours.split(/[.:]/);
    const hours = parseInt(hoursMinutes[0], 10);
    const minutes = hoursMinutes[1] ? parseInt(hoursMinutes[1], 10) : 0;
    return hours + minutes / 60;
};

const boundaries = [b1, b2, b3]
const errors = [];

boundaries.forEach((boundary, index, array) => {
    const a = timeStringToNumber(boundary.start);
    const b = timeStringToNumber(boundary.end);
    let c, d

    if (index + 1 === array.length) {
        c = timeStringToNumber(array[0].start);
        d = timeStringToNumber(array[0].end);
    } else {
        c = timeStringToNumber(array[index + 1].start);
        d = timeStringToNumber(array[index + 1].end);
    }

    if (b < c) {
        errors.push({
            start: b,
            end: c,
        })
    }
    
})

优化后实现

const timeStringToNumber = (time24Hours) => {
    const hoursMinutes = time24Hours.split(/[.:]/);
    const hours = parseInt(hoursMinutes[0], 10);
    const minutes = hoursMinutes[1] ? parseInt(hoursMinutes[1], 10) : 0;
    return hours + minutes / 60;
};

// 数值时间转回24小时制字符串,用于结果输出
const numberToTimeString = (timeNum) => {
    const hours = Math.floor(timeNum % 24);
    const minutes = Math.round((timeNum % 1) * 60);
    return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
};

const calculateTimeGaps = (boundaries) => {
    const gaps = [];
    // 转换时间格式,处理跨零点时段偏移
    const processedPeriods = boundaries.map(item => {
        let start = timeStringToNumber(item.start);
        let end = timeStringToNumber(item.end);
        // 跨零点时段给终点加24小时偏移,解决大小比较错误问题
        if (end < start) end += 24;
        return { id: item.id, start, end };
    });

    // 按时段起点升序排序,不受原始传入顺序影响
    processedPeriods.sort((a, b) => a.start - b.start);

    // 合并所有重叠、相邻的时段,消除重叠干扰
    const mergedPeriods = [];
    for (const period of processedPeriods) {
        if (mergedPeriods.length === 0) {
            mergedPeriods.push({...period});
            continue;
        }
        const lastMerged = mergedPeriods[mergedPeriods.length - 1];
        if (period.start <= lastMerged.end) {
            // 时段重叠/相邻,更新合并后时段的终点
            lastMerged.end = Math.max(lastMerged.end, period.end);
        } else {
            mergedPeriods.push({...period});
        }
    }

    // 计算非跨零点的普通相邻间隙
    for (let i = 0; i < mergedPeriods.length - 1; i++) {
        const currentEnd = mergedPeriods[i].end;
        const nextStart = mergedPeriods[i + 1].start;
        if (nextStart > currentEnd) {
            gaps.push({
                start: numberToTimeString(currentEnd),
                end: numberToTimeString(nextStart),
                durationHours: Number((nextStart - currentEnd).toFixed(2))
            });
        }
    }

    // 单独计算首尾跨零点间隙
    const firstPeriod = mergedPeriods[0];
    const lastPeriodEnd = mergedPeriods[mergedPeriods.length - 1].end % 24;
    if (lastPeriodEnd > firstPeriod.start) {
        gaps.push({
            start: numberToTimeString(lastPeriodEnd),
            end: numberToTimeString(firstPeriod.start),
            durationHours: Number(((firstPeriod.start + 24) - lastPeriodEnd).toFixed(2))
        });
    }

    return gaps;
};

// 场景1测试
console.log(calculateTimeGaps([b1, b2, b3]));
// 输出:[{start: "23:00", end: "01:00", durationHours: 2}] 符合预期

// 场景2测试
console.log(calculateTimeGaps([b1, b2, b3]));
// 输出:[{start: "06:00", end: "08:00", durationHours: 2}] 符合预期

优化点说明

  • 对跨零点时段做+24小时偏移处理,解决跨天时间大小比较逻辑错误的问题
  • 计算前先按时段起点排序,不受原始数组的时段传入顺序影响
  • 提前合并重叠、相邻的时段,彻底消除时段重叠场景对间隙判断的干扰
  • 单独处理首尾跨零点逻辑,通过模24运算还原真实时间点,准确识别跨零点间隙

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:24:40