检查自一周开始以来的时间(以分钟为单位)是否以不同的时间间隔介于两个值(自一周开始以来以分钟为单位的值)之间

Check if time in minutes since start of week is between two values (value in minutes since start of week) at different intervals

所以我正在使用 Zendesk API 来获取实例的时间表,API returns 一个包含名为间隔的数组的对象,如下所示:

[
  { "start_time": 1980, "end_time": 2460 },
  { "start_time": 3420, "end_time": 3900 },
  { "start_time": 4860, "end_time": 5340 },
  { "start_time": 6300, "end_time": 6780 },
  { "start_time": 7740, "end_time": 8220 }
]

此示例仅转换为一周中每个工作日的上午 9 点到下午 5 点(以分钟为单位),该值是自一周开始以来的分钟数,实际上是星期日的午夜(意味着 720 的值将是星期日的中午)周日)。

我正在尝试实现一些服务器端逻辑,循环遍历间隔并检查当前时间是否在给定日期的间隔之间,从而可以检测它当前是否在工作时间内。

我在想 moment.js 库可能对此有用,我一直在玩 .startOf('week').diff() 函数,但我一直被阻止,我担心它可能没有我想要的那么可靠,因为我不确定这周是周一还是周日开始。

到目前为止我有

let isBusinessHours = false;

function checkBusinessHours() {
  intervals.map((interval, key) => {
    //offset weekdays to match interval keys
    let currentDay = moment().weekday() -1; 

    //create comparison start & end times based on interval start & end times
    let startTime = moment().startOf('week').add(interval.start_time, 'minutes'); 
    let endTime = moment().startOf('week').add(interval.end_time, 'minutes');

    //check to see if it's business hours
    if (moment().isBetween(startTime, endTime) && currentDay === key) {
      isBusinessHours = true;
    } 
  })
  return isBusinessHours;
}

但我不确定这是否是最好的检查方法?

您可以获得一周的开始时间,然后向其中添加 start_time 和 end_time 分钟,这将得到调整后的 Date 对象,然后您可以使用该对象与当前日期。

我使用 date-fns 而不是 moment.js,但如果需要,您可以翻译代码。

const { startOfWeek, add, compareAsc, compareDesc } = require("date-fns")

const intervals = [
  { "start_time": 1980, "end_time": 2460 },
  { "start_time": 3420, "end_time": 3900 },
  { "start_time": 4860, "end_time": 5340 },
  { "start_time": 6300, "end_time": 6780 },
  { "start_time": 7740, "end_time": 8220 }
]

const startOfWeekDate = startOfWeek(new Date());
const now = new Date();
let isBusinessHour = false;
for (let i = 0; i < intervals.length; i++) {
  const startTime = add(startOfWeekDate, { minutes: intervals[i].start_time });
  const endTime = add(startOfWeekDate, { minutes: intervals[i].end_time });
  if (compareAsc(now, startTime) === 1 && compareDesc(now, endTime) === 1) {
    isBusinessHour = true;
  }
}

console.log("isBusinessHour", isBusinessHour)

请注意,startOfWeek 函数接受第二个参数来指定一周​​从哪一天开始(通常是星期日或星期一)

在遵守夏令时的地方,使用从周日开始的偏移量似乎不是一个好主意。大多数地方使用星期日作为转换日,因此在那些日子里,星期日不是 24 小时长,并且该周的所有偏移量将是 ± DST 偏移(以分钟为单位)。

忽略这个问题,将日期转换为偏移量相当简单:减去前一个星期日,然后将差值除以一分钟内的毫秒数。从偏移量转换为日期是相反的:将分钟添加到前一个星期日的日期,例如

// Return Date for start of Sunday 00:00 before d
function startOfWeek(d = new Date()) {
  return new Date(d.getFullYear(), d.getMonth(), d.getDate() - d.getDay());
}

// Convert a Date to an offset in minutes
// from start of previous Sunday
function dateToOffset(d = new Date()) {
  return Math.floor((d - startOfWeek(d)) / 6e4);  
}

// Convert an offset to date, default is current week
// Week starts on Sunday
function offsetToDate(offset, d = new Date()) {
  let date = startOfWeek(d);
  date.setMinutes(offset);
  return date;
}

// Examples
// Just a helper to format dates
function format(d) {
  return d.toLocaleString('en', {
    weekday: 'short',
    hour: '2-digit',
    hour12: false,
    minute: '2-digit'
  });
}

// Show current offset
let d = new Date();
console.log(`For ${format(d)} the offset is ${dateToOffset(d)}`);

// Convert offsets to dates
let data = [
  { "start_time": 1980, "end_time": 2460 },
  { "start_time": 3420, "end_time": 3900 },
  { "start_time": 4860, "end_time": 5340 },
  { "start_time": 6300, "end_time": 6780 },
  { "start_time": 7740, "end_time": 8220 }
];
data.forEach(o => console.log(
 `Start: ${format(offsetToDate(o.start_time))}  ` +
 `End  : ${format(offsetToDate(o.end_time))}`
));

// Find out if dates are between a start and end
[new Date(2021,10,25,12), // Thu 25 Nov 12:00
 new Date(2021,10,27,12), // Sat 25 Nov 12:00
 new Date()               // Now
].forEach(d => {
  let offset = dateToOffset(d);
  console.log(
    `Is ${format(d)} between a start and end? ` +
    `${!!data.find(obj => obj.start_time <= offset && obj.end_time > offset)? 'Yes' : 'No'}`
  )
});