【问题标题】:Can I check if event happened during an hour, regardless of date? Moment.js我可以检查事件是否在一小时内发生,无论日期如何? Moment.js
【发布时间】:2020-06-15 03:44:06
【问题描述】:

我正在跟踪设备的使用情况,并按小时向用户展示他们的使用趋势。基本上,我需要查看times 文档,看看设备是否在下午 6 点和晚上 7 点之间、晚上 7 点和晚上 8 点、晚上 8 点和晚上 9 点,等等所有 24 小时之间“开启”。

这是我最初写的:

      // loop through 24 hours of the day
      for (let j = 0; j < 24; j++) {
        const beginningOfHour = moment().startOf('day').add(j, 'hour').toDate()
        const endOfHour = moment(beginningOfHour).add({ m: 59, s: 59, ms: 999 }).toDate()

        const cumulativeHours = timePerPeriod(beginningOfHour, endOfHour, myTimes)  // calculation func

        trendsArray.push(cumulativeHours)
      }

这不起作用,因为 beginningOfHourendOfHour 也附有日期。

我不知道如何检查我的 times 文档中的小时部分,而没有任何日期参考。有关如何执行此操作的任何建议?

编辑: 这是times 文档的样子:

_id: 5e56cf9ae65bf2b30a6ab525  // ObjectID type
user_id: 5e56bb2b40ad526200401773  // ObjectID type
start: 2020-02-27T00:00:00.000+00:00  // Date type
stop: 2020-02-27T06:00:00.000+00:00  // Date type

设备可以开启任意时间长度,例如连续 3 个月或 15 秒。检查每个time 文档,如果它在该小时持续时间内打开任何长度的时间,我的计算函数(上面称为cumulativeHours)返回它在该小时内打开的长度(以毫秒为单位)。

【问题讨论】:

  • 数据是否可以包含超过一天的事件?如果是这样,它们是累积的吗? 例如如果过去一周的每一天我都在晚上 8:30 打开我的设备,它应该返回 7 吗? 另外,您能否提供它在 myTimes 变量中提供的示例数据?
  • 我用更多信息编辑了我的问题。
  • 您能否将 24 小时时间转换为名为 time 的整数并使用 time &gt; start &amp;&amp; time &lt; end

标签: javascript node.js datetime momentjs


【解决方案1】:

您可以通过对像这样的时刻对象使用.hour().minute() 方法来遍历时间并按时间戳的小时和/或分钟进行过滤(为简单起见,我只检查小时):

let sampleArrayOfDateTimes = [
  moment("2013-02-08 08:59"),
  moment("2013-02-08 09:00"),
  moment("2013-02-08 09:30"),
  moment("2013-02-08 10:00")
]

// find datetimes between 09:00 (including) and 10:00 (excluding)

let arrayWithTimesBetween9and10 = sampleArrayOfDateTimes.filter(datetime => datetime.hour() == 9);

console.log("the following datetimes are between 09:00 and 09:59");
arrayWithTimesBetween9and10.forEach(datetime => {
  console.log(datetime.format());
});
&lt;script src="https://unpkg.com/moment@2.24.0/moment.js"&gt;&lt;/script&gt;

【讨论】:

  • 我是这么想的,但他在问题中添加了细节。这实际上不是他想做的事
【解决方案2】:

由于问题已被编辑并且现在要求时间范围相互重叠,因此这里有一个编辑版本的解决方案。这是一种非常简化的方法,它不考虑多天的分钟或时间跨度,但它希望它传达了这个想法。基本上对于每个时间跨度组合都需要检查所有 4 个可能性(时间跨度完全重叠,根本不重叠或仅开始或仅介于两者之间):

let sampleDatetimeRanges = [
  {
    start: moment("2013-02-08 09:00"),
    end: moment("2013-02-08 10:00")
  },
  {
    start: moment("2013-02-08 08:00"),
    end: moment("2013-02-08 12:00")
  },
  {
    start: moment("2013-02-08 13:00"),
    end: moment("2013-02-08 18:00")
  } 
];

function isBetweenHours(start, end, hourInQuestion) {
  return start <= hourInQuestion && end >= hourInQuestion;
}


// calculate the timespan between 09:00 and 10:00
const rangeStart = 9;
const rangeEnd = 11;
const hoursCount = sampleDatetimeRanges.map(current => {
  let startHour = current.start.hour();
  let endHour = current.end.hour();
  if (startHour <= rangeStart && endHour >= rangeEnd) { // full time covered
    return rangeEnd - rangeStart;
  } else if (startHour <= rangeStart && isBetweenHours(rangeStart, rangeEnd, endHour)) { // only end time in timespan
    return endHour - rangeStart;
  } else if (isBetweenHours(rangeStart, rangeEnd, startHour) && endHour >= rangeEnd) { // only start time in timespan
    return rangeEnd - startHour;
  } else if (isBetweenHours(rangeStart, rangeEnd, startHour) && isBetweenHours(rangeStart, rangeEnd, endHour)) {
    return endHour - startHour;
  }
  // not in timespan
  return 0;

}).reduce((sum, current) => sum + current, 0)

console.log(`hours covered in the timespan from ${rangeStart} to ${rangeEnd}: ${hoursCount}. `);
&lt;script src="https://unpkg.com/moment@2.24.0/moment.js"&gt;&lt;/script&gt;

【讨论】:

  • let startHour = current.start.hour(); 你拥有的这条线或多或少是我需要的,但 .hour() 不是javascript Date 对象的有效方法。 getTime() 方法返回 unix 时间戳,这也不是我需要的。
  • @Brian 为什么不像我那样将它转换/解析为momentjs-objects?您已将 momentjs 作为标签添加到您的问题中。
猜你喜欢
  • 2021-08-27
  • 1970-01-01
  • 1970-01-01
  • 2015-01-23
  • 1970-01-01
  • 2011-06-13
  • 2014-09-13
  • 2019-03-03
  • 2011-02-15
相关资源
最近更新 更多