Check if time range overlaps with another time range - javascript

Assume i have a start date and a end data as follows
end: "2021-10-22T06:00:00.000Z"
start: "2021-10-22T05:00:00.000Z"
I want to check if another given time range overlaps with the above time range in javascript. I tried using moment as follows.
return (
moment(timerange1.duration.end) <= moment(timerange2.duration.start) ||
moment(timerange1.duration.start) >= moment(timerange2.duration?.end)
);
But this does not produce the correct results. What would be the correct way to check if a certain time range overlaps with another time range using javascript?

Consider this:
In case A and C they do not overlap.
But what is true in B that isn't true in A or C?
Well, the start, or the end of the red one, is between the start and end of the blue one. That will always be true for overlapping timeperiods.
Example code:
if( (red.start > blue.start && red.start < blue.end) || (red.end > blue.start && red.end< blue.end) ) {
// do something
}

return (
(moment(timerange1.duration.start) >= moment(timerange2.duration.start) && moment(timerange1.duration.start) <= moment(timerange2.duration.end))
|| (moment(timerange1.duration.end) >= moment(timerange2.duration.start) && moment(timerange1.duration.end) <= moment(timerange2.duration.end))
|| (moment(timerange2.duration.start) >= moment(timerange1.duration.start) && moment(timerange2.duration.start) <= moment(timerange1.duration.end))
)
there are 3 different cases to consider as overlap
timerange1: |-----|
timerange2:     |-----|
timerange1:     |-----|
timerange2: |-----|
timerange1: |-----------|
timerange2:     |-----|

You can use the twix.js plugin for moment to handle the date ranges. In your code, you need to do something like that. This is sample code snippet you can modify it according to your need.
var t1 = {
start: "1982-01-25T09:30",
end: "1982-01-25T13:30",
};
var t2 = {
start: "1982-01-23T13:30",
end: "1982-01-25T12:30",
};
var t3 = {
start: "1982-01-24T13:30",
end: "1982-01-25T10:30",
};
var t1Range = moment(t1.start).twix(t1.end);
var t2Range = moment(t2.start).twix(t2.end);
var t3Range = moment(t3.start).twix(t3.end);
t1Range.overlaps(t2Range) || t1Range.overlaps(t3Range); //=> true

Related

data range in TypeScript

Update:
I have several objects with start dates and end date
When inserting / modifying an object, the starting or ending date of the new object can not be included in the existing object.
Exist : 06/06/2018-----30/06/2018
can input:
04/06/2018-------05/06/2018
02/02/2018------ until less than date Start of which exists (05/06/2018)
or higher:
31/06/2018--------
can not get in :
04/06/2018-------07/06/2018 The end is already understood between the beginning and the end exists.
Or
07/06/2018---08/06/2018 because it is also included between the beginning and the end of the.
Code:
validateParamsDates(url, newConfig) {
return this.http.get<any>(url).pipe(map(param => {
let messageError = { message: "", showAlert: false };
let userStart = newConfig.startdatevalidity;
let userFinish = newConfig.enddatevalidity;
param[1]['params'].array.forEach(element => {
if(userStart > element.startdatevalidity && userFinish > element.enddatevalidity
|| userStart < element.startdatevalidity && userFinish < element.enddatevalidity
&& userStart > element.enddatevalidity
){
console.log('good');
}else{
console.log('=(');
}
});
return messageError ;
}));
}
You should first convert the strings to a Date object. Then you can compare dates and everything will work as it should ;)
So you would do something like:
const start2: Date = new Date(Object2.start);
const end1: Date = new Date(Object1.end);
if (start2 > end1) { console.log('good'); }
Please also note that in order for all of this to work in javascript, the dates should be defined in MM/DD/YYYY format not in DD/MM/YYYY
I would probably do something like this.
var start = new Date(Object2.start);
var end = new Date(Object1.end);
if(start.getTime() > end.getTime()) console.log('good');
Similar to this answer: Compare two dates with JavaScript

Comparision between 2 Object

I am working on a course registration system.I need to check for time conflicts.
Already registered courses object:
{"00001":{"days":"Monday-Tuesday","hours":"11:40-12:30*13:40-15:30"}}
this means that 00001 course is in monday 11:40-12:30 in tuesday 13:40-15:30
Courses to register object:
{"00003":{"days":"Friday","hours":"9:40-10:40"}}
I have managed to check is student already registered to course with this code:
Object.keys(registeredcoursesobject).forEach(function(key){
if( Object.keys(coursestoregisterobject).includes(key)) {
alert("You have already registered to "+key+" crn number course");
//return;
}
});
A course can be at most 2 days in a week and in 1 different time intervals(what if 2 time intervals??) which means that there will be only one "-" in days property and only one "*" in hours property.
I am new to programming and working on this for days any ideas ?
I hope this answer is still relevant for you. Here is what I have:
var registeredcoursesobject = {"00001":{"days":"Monday-Thursday","hours":"11:40-12:30*16:30-18:30"}}
var coursestoregisterobject = {"00002":{"days":"Monday-Friday","hours":"10:40-15:30*16:40-18:00"}}
var getTicks = function(timeStr) {
return new Date('1970-01-01T' + timeStr + ':00Z').getTime();
}
Object.keys(registeredcoursesobject).forEach(function(rKey){
if( Object.keys(coursestoregisterobject).includes(rKey)) {
alert("You have already registered to "+rKey+" crn number course");
return false;
};
Object.keys(coursestoregisterobject).forEach(function(cKey){
var regDays = registeredcoursesobject[rKey].days.split('-');
var regHours = registeredcoursesobject[rKey].hours.split('*');
var courseDays = coursestoregisterobject[cKey].days.split('-');
var courseHours = coursestoregisterobject[cKey].hours.split('*');
regDays.forEach(function(rDay, i) {
var rHourRange = regHours[i];
// I assume you need to check there is same date/time pain in registeredcoursesobject and coursestoregisterobject
courseDays.forEach(function(cDay, j) {
if (rDay == cDay) {
var cHourRange = courseHours[j];
// now, do you need to compare hours be equal exactly or do you need to check time overlap?
// assume you just need to ckeck hour ranges are equal, then:
if (rHourRange == cHourRange){
// means equal
alert("You have already registered to "+cKey+" crn number course on day "+cDay+" at "+cHourRange+" hours.");
return true;
}
// if you need to check range overlap
var rTime = rHourRange.split('-');
rTimeRange = [getTicks(rTime[0]), getTicks(rTime[1])];
rStartT = Math.min.apply(null, rTimeRange), rEndT = Math.max.apply(null, rTimeRange);
var cTime = cHourRange.split('-');
cTimeRange = [getTicks(cTime[0]), getTicks(cTime[1])]
cStartT = Math.min.apply(null, cTimeRange), cEndT = Math.max.apply(null, cTimeRange);
// now your rangeTime is a pair of int values, that represent time range rStartT:rEndT
// and your courseTime is a pair of int values cStartT:cEndT
// so now you just check the overlap of two integer pais.
// according to this: https://stackoverflow.com/questions/3269434/whats-the-most-efficient-way-to-test-two-integer-ranges-for-overlap#answer-3269471
if (rStartT < cEndT && cStartT < rEndT) {
alert("You have already registered to "+cKey+" crn number course on day "+cDay+" within time range "+cHourRange+" hours overlap with "+rHourRange+" time range.");
// means time ranges are overlap at some range. But I don't count the border, like "14:00-15:00" and "15:00-16:00" do not overlap
// otherwise replace < with <=
return true;
}
}
})
});
return false;
});
});
I am making some assumptions here about your task.
UPDATE: added time range check.
UPDATE: check keys equal first and values swap if start time is for some reason is bigger than end time.

How can I apply a custom filter to ng-repeat only when there is a value in the textfield?

I have an array that I'm trying to filter through. I have several filters being used, but one of them is to filter objects out that don't fall in a range of years specified by the user. Here is the HTML
<input type="text" ng-model="minYear" placeholder="Start Year">
<input type="text" ng-model="maxYear" placeholder="End Year">
Here is the ng-repeat
<img ng-src="{{pic.imgPath}}" ng-repeat="pic in pictures
| orderBy : 'title' | filter:{other filters} | filter:yearFilterFunction"/>
Here is the yearFilterFunction that I am using to filter. And note, this works when there are values present. So if the picture was from 2001, and you put in 2000 for the minYear and 2005 for the maxYear, it will show. But When the page loads, and there is nothing in these values....nothing in the array shows up in the repeat. I tried declaring these variables beforehand, but then it just looks funny when the user goes in and sees 1900 and 2016 in these two inputs.
Here is the Javascript
$scope.minYear = 1900;
$scope.maxYear = 2016;
$scope.yearFilterFunction = function(picture){
return (picture.year >= $scope.minYear && picture.year <= $scope.maxYear);
}
Thanks in advance!
I think this one will work for you : a working fiddle link
The point is, you don't need to set the minYear and maxYear beforehand, so the value will be treated as undefined at beginning, but when user type anything and erase that value to empty, the model value will be changed to ''. So the regex will suit this situation pretty well :
$scope.yearFilterFunction = function(picture){
var regObj = new RegExp('[0-9]+');
return (
(!regObj.test($scope.minYear) || picture.year >= $scope.minYear)
&& (!regObj.test($scope.maxYear) || picture.year <= $scope.maxYear)
);
This handles all the 4 cases
1) when both are set
2)when only minYear is set
3) when only maxYear is set
4) when both are not set . In this case display all
$scope.yearFilterFunction = function(picture){
return
($scope.minYear && $scope.maxYear && picture.year >= $scope.minYear && picture.year <= $scope.maxYear) ||
($scope.minYear && !scope.maxYear && picture.year >= $scope.minYear) ||
($scope.maxYear && !scope.minYear && picture.year <= $scope.maxYear) ||
(!$scope.maxYear && !scope.minYear);
}
I used an alternate approach to solve this issue. I wrote a custom filter which will accept the start year and end year and then filter out the years in between them. Check this fiddle here.
Filter
myApp.filter("yearFilter", function() {
return function(years, startYear, endYear) {
var filteredYears = years;
if (!isNaN(startYear)) {
filteredYears = _.filter(filteredYears, function(year) {
return year >= startYear;
});
}
if (!isNaN(endYear)) {
if (isNaN(startYear) || (parseInt(startYear) < parseInt(endYear))) {
filteredYears = _.filter(filteredYears, function(year) {
return year <= endYear;
});
}
}
return filteredYears;
}
});
Basically the filter is checking whether your start year/end year is a number and based on that it will do the filtering. It will also handle situations where only the start year or the end year is valid. I have assumed a scenario where if the end year is lesser that the start year, it will only filter by the start year.
HTML
<input type="text" ng-model="minYear" placeholder="Start Year">
<input type="text" ng-model="maxYear" placeholder="End Year">
<div ng-repeat="year in years | yearFilter: minYear: maxYear">
{{year}}
</div>

set datepicker kendo ui, java script

I try to set 2 datepickers with a click event.
my code looks like this
$('#previous3Days').click(function () {
var a = $('#MonthBis').data('kendoDatePicker').value();
var d = $('#MonthVon').data('kendoDatePicker').value();
d.setDate(d.getDate() - 3);
$('#MonthVon').data('kendoDatePicker').value(d);
$('#MonthBis').data('kendoDatePicker').value(a);
if (a !== d) {
$('#MonthBis').data('kendoDatePicker').value(a);
a.setDate(a.getDate() - 3);
}
});
my problem is that the KendoComboBox don't change the value of the "Monthbis".
i tried every possibility like if (a>d) or (a!=d).
If i use (a>=d) every click both dates get changed.
i also checked the console in my browser according to this both dates are always the same and i don't see my fault.
I think that the problem is in the logic of your program...
Changing MonthVon is ok since you (in order) you wrote:
var d = $('#MonthVon').data('kendoDatePicker').value(); // Line 4
d.setDate(d.getDate() - 3); // Line 5
$('#MonthVon').data('kendoDatePicker').value(d); // Line 7
But for MonthBis the logic is pretty odd... This is what you wrote:
var a = $('#MonthBis').data('kendoDatePicker').value(); // Line 3
$('#MonthBis').data('kendoDatePicker').value(a); // Line 8
So you did nothing so far since you read and write the same value.
Then you check that a !== c and if so you do:
$('#MonthBis').data('kendoDatePicker').value(a); // Line 10
a.setDate(a.getDate() - 3); // Line 11
You modify a but you do nothing with it's value so it actually does nothing.
Probably, you should swap lines 10 and 11 so you would have:
$('#previous3Days').click(function () {
var d = $('#MonthVon').data('kendoDatePicker').value();
d.setDate(d.getDate() - 3);
$('#MonthVon').data('kendoDatePicker').value(d);
var a = $('#MonthBis').data('kendoDatePicker').value();
if (a !== d) {
a.setDate(a.getDate() - 3);
$('#MonthBis').data('kendoDatePicker').value(a);
}
});

compare start "Time" is less than the end "Time" in javascript

I have a value in two text fields which is already formatted as hh:mm, How can I compare the values of these two fields?
I am trying the following code:
function check_ToFromTime(toTime) {
if (getControl('txtStartTimeFrom').value == '00:00' && getControl(toTime).value == '00:00') { return true; }
var fromDate = new Date(getControl('txtStartTimeFrom').value);
var toDate = new Date(getControl('txtEndTimeTo').value);
var fromT = fromDate.getTime();
var toT = toDate.getTime();
return (toT >= fromT);
}
the if statement in the first line works, but the last statement
return (toT >= fromT);
does not work. it always returns false. where am i going wrong?
I wouldn't worry about converting these String objects to Date objects. Just split the string and compare:
var fromDate = "04:05";
var toDate = "04:04";
var fromTokens = fromDate.split(":");
var toTokens = toDate.split(":");
alert(fromTokens[0] < toTokens[0] || (fromTokens[0] == toTokens[0] && fromTokens[1] < toTokens[1]));
You could place this functionality in a nice function for re-usability:
function isAfter(fromDate, toDate){
var fromTokens = fromDate.split(":");
var toTokens = toDate.split(":");
return (fromTokens[0] < toTokens[0] || (fromTokens[0] == toTokens[0] && fromTokens[1] < toTokens[1]));
}
//Tests
alert(isAfter("04:04", "05:05"));
alert(isAfter("06:04", "05:05"));
alert(isAfter("05:05", "05:05"));
JS Fiddle: http://jsfiddle.net/X5v5F/
I'm not going to head down this route, since I think splitting the strings is sufficient, but if you were fixed on a date, I would recommend using Moment.js.
it will always print false because end time will always be greater than start time.U need to change the condition i.e. return (toT <= fromT);

Categories

Resources