使用 JavaScript 比较时间范围

Use JavaScript to compare time ranges

我有一个日期对象形式的时间范围集合。我需要将这些时间范围与新时间范围进行比较,以确保我添加的时间范围不会与现有时间范围重叠或重复。

这是一个集合示例。

var timeSlots = [
    {
        BeginTime: new Date("10/25/2015 8:00 AM"),
        EndTime: new Date("10/25/2015 8:45 AM")
    },
    {
        BeginTime: new Date("10/25/2015 9:00 AM"),
        EndTime: new Date("10/25/2015 9:45 AM")
    },
    {
        BeginTime: new Date("10/25/2015 9:50 AM"),
        EndTime: new Date("10/25/2015 10:30 AM")
    }
];

在前面的示例中,日期的日期部分无关紧要。时代如此。

如果我有一个从 9:30 AM 开始的新时间范围对象,我需要能够检测到它。

这是 AngularJS 应用程序的内部,它可以访问 MomentJS 和 Angular Moment。

如何获取新的时隙对象并确保它不会与现有的其他对象发生冲突?

// building off of the previous example
var newTimeSlot = newDate("10/25/2015 9:00 AM");
if (!conflictingTime(newTimeSlot)) {
    // then run my code
}

function conflictingTime(time) {
    // how do I do this?
}

由于这是一个开源项目,我希望这里有人喜欢 SO 点足以提出比我所做的更 "best practice" 或更优雅的解决方案。我想评论中的每个人都讨厌 SO 点。

这是我的解决方案。

angular.forEach($scope.timeSlots, function (timeSlot, index) {
    var beginTimeHasIssue = ($scope.timeSlot.BeginTime >= timeSlot.BeginTime && $scope.timeSlot.BeginTime <= timeSlot.EndTime);
    var endTimeHasIssue = ($scope.timeSlot.EndTime >= timeSlot.BeginTime && $scope.timeSlot.EndTime <= timeSlot.EndTime);

    if (beginTimeHasIssue || endTimeHasIssue) {
        hasError = true;
        $scope.HasTimeSlotError = true;
        return;
    } 
});

你这样做的方式与建议的一样,但它似乎并不可靠,例如如果没有当前插槽,forEach 将不会做太多事情。此外,它会一直走到尽头,而不是在找到插槽后停止。考虑以下因素:

var timeSlots = [
  {BeginTime: new Date("10/25/2015 8:00 AM"),
   EndTime: new Date("10/25/2015 8:45 AM")},
  {BeginTime: new Date("10/25/2015 9:00 AM"),
   EndTime: new Date("10/25/2015 9:45 AM")},
  {BeginTime: new Date("10/25/2015 9:50 AM"),
   EndTime: new Date("10/25/2015 10:30 AM")}
];

/*  @param   {Object} slot - object with BeginTime and EndTime date objects
 **  @returns {Boolean} true if slot fits, otherwise false
 */
function slotFits(slot) {
  if (timeSlots.length == 0) return true; // If no slots, must fit
  return timeSlots.some(function(s, i) {
    return (i == 0 && slot.EndTime <= s.BeginTime) || // slot is before all others
      (s.EndTime <= slot.BeginTime && !timeSlots[i + 1]) || // slot is after all others
      (s.EndTime <= slot.BeginTime && timeSlots[i + 1].BeginTime >= slot.EndTime) // Slot between others
  });
}

[{BeginTime: new Date("10/25/2015 7:00 AM"),  // before all, true
  EndTime: new Date("10/25/2015 8:00 AM")},
 {BeginTime: new Date("10/25/2015 10:30 AM"),  // after all, true
  EndTime: new Date("10/25/2015 11:00 AM")},
 {BeginTime: new Date("10/25/2015 8:45 AM"),  // between 0 and 1, true
  EndTime: new Date("10/25/2015 9:00 AM")},
 {BeginTime: new Date("10/25/2015 8:45 AM"),  // Overlap 1, false
  EndTime: new Date("10/25/2015 9:15 AM")}
].forEach(function(slot, i) {
  console.log('Slot ' + i + ': ' + slotFits(slot));
});

这也可以优化为一旦找到插槽就停止,需要多两行代码。您应该能够根据您的 angular 代码调整它。

PS。我通常不会使用字符串以这种方式创建日期(即使用非标准字符串的内置解析器),但这对于这个例子来说已经足够了。日期确实应该使用类似以下内容创建:

var date = moment('10/25/2015 9:15 AM', 'MM/DD/YYYY h:mm Z').toDate();

console.log(date.toString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>

   addTimeSlot=function(newtimeSlot){
        var beginTimeHasIssue = false;
        var endTimeHasIssue = false;
        timeSlots.forEach(function (timeSlot, index) {
            if( newtimeSlot.BeginTime >= timeSlot.BeginTime &&  newtimeSlot.EndTime <= timeSlot.EndTime ) {
                 console.log('falls inbetween');
                endTimeHasIssue = true;
            } 
            if( newtimeSlot.BeginTime <= timeSlot.BeginTime &&  newtimeSlot.EndTime >= timeSlot.EndTime) {
                 console.log('falls inbetween');
                beginTimeHasIssue = true;
            }      
        });
        if (beginTimeHasIssue || endTimeHasIssue) {
            console.log('error');
            return;
        } else {
            timeSlots.push(newtimeSlot)
            console.log('saved');
        }
        if (timeSlots.length == 0) {
          timeSlots.push(newtimeSlot);
        }
    }