【问题标题】:Check if time in minutes since start of week is between two values (value in minutes since start of week) at different intervals检查自一周开始以来的时间(以分钟为单位)是否在不同间隔的两个值(自一周开始以来的分钟数)之间
【发布时间】:2022-01-04 10:24:00
【问题描述】:

所以我使用 Zendesk API 来获取实例的计划,API 返回一个对象,其中包含一个名为间隔的数组,如下所示:

[
  { "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;
}

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

【问题讨论】:

  • 真正的问题是什么?您可以尝试moment.js documentation:“moment#startOf('week') 使用区域设置感知周开始日。”这似乎是一个坏主意,因为不同的文化在一周的第一天有不同的与地点或语言无关。还有startOf('isoWeek'),至少提供了确定性(周一00:00:00)。

标签: javascript node.js datetime momentjs zendesk-api


【解决方案1】:

您可以获取一周的开始时间,然后将 start_time 和 end_time 分钟添加到其中,这将为您获取调整后的 Date 对象,然后您可以使用该对象与当前 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 函数接受第二个参数来指定一周​​从哪一天开始(通常是星期日或星期一)

【讨论】:

    【解决方案2】:

    在遵守夏令时的地方使用从周日开始的偏移量似乎不是一个好主意。大多数地方都将星期日作为转换日,因此在那些日子里,星期日不是 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'}`
      )
    });

    【讨论】:

    • 谢谢你,这给了我更多的线索,我需要停止回避原生日期 API。我已经接受了这个答案。
    猜你喜欢
    • 2019-08-10
    • 1970-01-01
    • 1970-01-01
    • 2021-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-03
    • 1970-01-01
    相关资源
    最近更新 更多