使用 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);
}
}
我有一个日期对象形式的时间范围集合。我需要将这些时间范围与新时间范围进行比较,以确保我添加的时间范围不会与现有时间范围重叠或重复。
这是一个集合示例。
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);
}
}