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

如何高效计算距离商家开门的时长?(JavaScript)

如何高效计算距离商家下次开门的时长(无需遍历)

问题描述

我需要计算任意时间点距离商家下次开门的时长(若当前商家已开门则返回0)。目前我通过遍历每一小时的方式实现了功能,想问问有没有不用遍历、更高效的JavaScript实现方案?

现有实现代码

function calcOpen(inputDate, scheduleObj){
  var d = inputDate;
  var n = d.getDay();
  var now = d.getHours() + "." + d.getMinutes();
  var delayHours = 0;

  for (let i = 0; i < 168; i++) {
    d = addHours(new Date(), i);
    n = d.getDay();
    now = d.getHours() + "." + d.getMinutes();
    day = scheduleObj[n];
    if (now > day[1] && now < day[2] || now > day[3] && now < day[4]) { 
        delayHours = i;
        break; 
        }
  }
 return addHours(new Date(), delayHours);
}

function addHours(date, hours) {
    date.setHours(date.getHours() + hours);
    return date;
}


var schedule = [
        ["Sunday", 9.30, 12.00, 15.30,22.00],
        ["Monday", 8.30, 12.00, 15.30,19.00],
        ["Tuesday", 8.30, 12.00, 15.30,19.00],
        ["Wednesday", 8.30, 12.00, 15.30,19.00],
        ["Thursday", 8.30, 12.00, 15.30,19.00],
        ["Friday",],
        ["Saturday", 8.00, 13.00]
        ];

var inDate = new Date();
var outdate = new Date();
outdate = calcOpen(inDate, schedule)
console.log('Input Date: ' + inDate);
console.log('Output Date: ' + outDate);

高效实现方案

原代码的问题在于遍历168小时(一周),不仅效率低,还存在时间计算错误(比如把9:30转成9.30作为数字,实际是9.5小时而非9.3小时)。下面是无需遍历的高效实现,核心思路是直接计算当前时间与各营业时段的时间差,而非逐小时检查:

// 辅助函数:将小时格式的数字(如9.30)转换成当天的分钟数
function timeToMinutes(time) {
    const hours = Math.floor(time);
    const minutes = Math.round((time - hours) * 100); // 处理9.30这类格式为9小时30分
    return hours * 60 + minutes;
}

// 辅助函数:给日期添加指定分钟数
function addMinutes(date, minutes) {
    const newDate = new Date(date);
    newDate.setMinutes(newDate.getMinutes() + minutes);
    return newDate;
}

function calcNextOpenTime(inputDate, schedule) {
    const now = new Date(inputDate);
    const currentDay = now.getDay();
    const currentMinutes = now.getHours() * 60 + now.getMinutes();
    const oneDayMinutes = 24 * 60;

    // 先检查当前日期是否在营业中
    const todaySchedule = schedule[currentDay];
    if (todaySchedule.length > 1) {
        // 处理多个营业时段
        for (let i = 1; i < todaySchedule.length; i += 2) {
            const openTime = timeToMinutes(todaySchedule[i]);
            const closeTime = timeToMinutes(todaySchedule[i + 1]);
            // 如果当前时间在营业时段内,返回当前时间
            if (currentMinutes >= openTime && currentMinutes < closeTime) {
                return new Date(now);
            }
        }
    }

    // 计算当天是否还有未开始的营业时段
    if (todaySchedule.length > 1) {
        for (let i = 1; i < todaySchedule.length; i += 2) {
            const openTime = timeToMinutes(todaySchedule[i]);
            if (currentMinutes < openTime) {
                // 当天还有开门时间,计算时间差
                const delayMinutes = openTime - currentMinutes;
                return addMinutes(now, delayMinutes);
            }
        }
    }

    // 当天已无营业时段,检查后续日期
    for (let dayOffset = 1; dayOffset < 7; dayOffset++) {
        const targetDay = (currentDay + dayOffset) % 7;
        const targetSchedule = schedule[targetDay];
        if (targetSchedule.length > 1) {
            // 取该天第一个营业时段的开始时间
            const firstOpenTime = timeToMinutes(targetSchedule[1]);
            // 计算距离该时段的总分钟数:(dayOffset天的分钟数) + 当天开始到开门的分钟数
            const delayMinutes = dayOffset * oneDayMinutes + (firstOpenTime - currentMinutes);
            return addMinutes(now, delayMinutes);
        }
    }

    // 如果一周都没营业(极端情况),返回null
    return null;
}

// 测试代码
var schedule = [
    ["Sunday", 9.30, 12.00, 15.30, 22.00],
    ["Monday", 8.30, 12.00, 15.30, 19.00],
    ["Tuesday", 8.30, 12.00, 15.30, 19.00],
    ["Wednesday", 8.30, 12.00, 15.30, 19.00],
    ["Thursday", 8.30, 12.00, 15.30, 19.00],
    ["Friday"],
    ["Saturday", 8.00, 13.00]
];

var inDate = new Date();
var outDate = calcNextOpenTime(inDate, schedule);
console.log('Input Date: ' + inDate);
console.log('Next Open Date: ' + outDate);

方案优势

  • 无逐小时遍历:最多循环7天(一周),远低于原168次循环,效率大幅提升
  • 时间计算精准:将时间统一转换成分钟数比较,避免了原代码中9.30作为数字的精度错误
  • 逻辑清晰:分三步处理:当前时段检查、当天剩余时段检查、后续日期检查,覆盖所有场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 18:43:10