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

如何简化TypeScript/Node中基于Moment.js的下次营业时间计算?

计算距离下一个营业时间的简便方案

我在TypeScript/Node项目中用Moment.js,通过const currentTime = moment()获取当前时间,需要计算商家距离下一个营业时间的时长。商家规则是周一至周五9:00-17:00:比如周一晚7点,距离周二9点还有14小时;周六晚9点,距离周一9点则是36小时。

我知道堆一堆if语句能实现,但觉得这是很常见的场景,应该有现成的库或者Moment.js内置方法,找了半天没头绪,想问有没有更简洁的解决办法?

我当前的实现代码

const currentTime = moment();
const opening = moment('9:00am', 'h:mma');
const midnight = moment('12:00am', 'h:mma');
const nineAMNextDay = opening.add(1, 'day');
let timeUntilBusinessHours;
if (currentTime.day() === 1 || currentTime.day() === 2 || currentTime.day() === 3 || currentTime.day() === 4) {
      if (currentTime.isAfter(opening)) {
        timeUntilBusinessHours = nineAMNextDay.diff(currentTime, 'seconds');
      } else {
        timeUntilBusinessHours = opening.diff(currentTime, 'seconds');
      }
    } else if (currentTime.day() === 5) {
      if (currentTime.isBefore(opening)) {
        timeUntilBusinessHours = opening.diff(currentTime, 'seconds');
      } else {
        timeUntilBusinessHours = midnight.diff(currentTime, 'seconds') + 205200;
      }
    } else if (currentTime.day() === 6) {
      timeUntilBusinessHours = midnight.diff(currentTime, 'seconds') + 118800;
    } else if (currentTime.day() === 0) {
      timeUntilBusinessHours = midnight.diff(currentTime, 'seconds') + 32400;
    }

优化方案1:用Moment.js简化逻辑(无需额外库)

原代码存在隐藏问题:opening.add(1, 'day')会直接修改opening对象本身,导致后续判断出错。下面的写法用clone()避免这个问题,同时把逻辑结构化,减少冗余:

import moment from 'moment';

const getTimeUntilNextOpening = (currentTime: moment.Moment): number => {
  const OPENING_HOUR = 9;
  const currentDay = currentTime.day(); // 0=周日,1=周一,…,6=周六
  let nextOpening: moment.Moment;

  // 克隆当前时间,避免修改原对象
  const todayOpening = currentTime.clone().hour(OPENING_HOUR).minute(0).second(0);

  switch(currentDay) {
    case 1: case 2: case 3: case 4: // 周一至周四
      nextOpening = currentTime.isBefore(todayOpening) ? todayOpening : todayOpening.add(1, 'day');
      break;
    case 5: // 周五
      nextOpening = currentTime.isBefore(todayOpening) ? todayOpening : todayOpening.add(3, 'day');
      break;
    case 6: // 周六
      nextOpening = todayOpening.add(2, 'day');
      break;
    default: // 周日
      nextOpening = todayOpening.add(1, 'day');
      break;
  }

  return nextOpening.diff(currentTime, 'seconds');
};

// 使用示例
const currentTime = moment();
const timeUntilBusinessHours = getTimeUntilNextOpening(currentTime);

优化方案2:用专门的营业时间处理库

如果后续可能遇到更复杂的营业时间规则(比如节假日、分时段营业),可以用moment-business-hours这个库,直接配置规则就能自动计算下一个营业时间:

import moment from 'moment';
import 'moment-business-hours';

// 全局配置营业时间:周一至周五9:00-17:00
moment.updateLocale('en', {
  workinghours: {
    workingtime: [['09:00', '17:00']],
    workingdays: [1, 2, 3, 4, 5] // 对应周一到周五
  }
});

const currentTime = moment();
// 获取下一个营业开始时间
const nextOpening = moment(currentTime).businessAdd(0, 'hours');
const timeUntilBusinessHours = nextOpening.diff(currentTime, 'seconds');

这个库会自动处理跨周末、非工作日的情况,不用自己写日期判断逻辑,代码更简洁易维护。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 14:25:33