How to check if two arrays of dates have matching items? - javascript

I have two arrays of dates. The first one have all the booked dates and the second one will have dates between "start day" and "end day" which user will pick.
Now I have to confirm that the days between the start and stop will not be found from the fully booked dates array.
I'm using Vue.js to update data.
Here is what I have done to get those dates:
/**
* Get dates from datepicker and format it to the same format that fully booked array has it's dates.
**/
var day1 = moment( this.startDate, 'DD/MM/Y').format('Y,M,D');
var day2 = moment( this.endDate, 'DD/MM/Y').format('Y,M,D');
var start = new Date(day1);
var end = new Date(day2);
/**
* Get dates between start and stop and return them in the dateArray.
**/
Date.prototype.addDays = function(days) {
var dat = new Date(this.valueOf());
dat.setDate(dat.getDate() + days);
return dat;
};
function getDates(startDate, stopDate) {
var dateArray = [];
var currentDate = startDate;
while (currentDate <= stopDate) {
dateArray.push(currentDate);
currentDate = currentDate.addDays(1);
}
return dateArray;
}
var dateArray = getDates(start, end);
/**
* Set dateArray in to Vue.js data.
**/
this.$set('daysBetweenStartStop', dateArray);
/**
* Get arrays of dates from the Vue.js data. calendar = Booked dates | matchingDays = Dates between start and stop.
**/
var calendar = this.fullDates;
var matchingDays = this.daysBetweenStartStop;
/**
* #description determine if an array contains one or more items from another array.
* #param {array} haystack the array to search.
* #param {array} arr the array providing items to check for in the haystack.
* #return {boolean} true|false if haystack contains at least one item from arr.
*/
var findIfMatch = function (haystack, arr) {
return arr.some(function (v) {
return haystack.indexOf(v) >= 0;
});
};
var matching = findIfMatch(calendar, matchingDays);
/**
* Check the results. If false we are good to go.
**/
if (matching){
alert('WE FOUND A MATCH');
} else {
alert('GOOD TO GO');
}
Arrays are in the following format:
var calendar = [
Sun Oct 02 2016 00:00:00 GMT+0300 (EEST),
Sun Oct 09 2016 00:00:00 GMT+0300 (EEST),
Sun Oct 16 2016 00:00:00 GMT+0300 (EEST),
Sun Oct 23 2016 00:00:00 GMT+0300 (EEST),
Sun Oct 30 2016 00:00:00 GMT+0300 (EEST)
]
var matchingDays = [
Fri Oct 28 2016 00:00:00 GMT+0300 (EEST),
Sat Oct 29 2016 00:00:00 GMT+0300 (EEST),
Sun Oct 30 2016 00:00:00 GMT+0300 (EEST)
]
My problem is that even if those two arrays have exactly same dates they will still somehow be considered as a not identical. Any ideas how to get this working?

Your match function should look like this :
findIfMatch = function (haystack, arr){
var i = 0;//array index
var j = 0;//array index
while(j < arr.length && i < haystack.length){
cur_cal = Date.parse(haystack[i]);
cur_match = Date.parse(arr[j]);
if(cur_cal > cur_match){
j++;
}else if(cur_cal < cur_match){
i++;
}else{
return true;
}
}
return false;
}

To get matching records from two array use this
var calendar = [
Sun Oct 02 2016 00:00:00 GMT+0300 (EEST),
Sun Oct 09 2016 00:00:00 GMT+0300 (EEST),
Sun Oct 16 2016 00:00:00 GMT+0300 (EEST),
Sun Oct 23 2016 00:00:00 GMT+0300 (EEST),
Sun Oct 30 2016 00:00:00 GMT+0300 (EEST)
];
var matchingDays = [
Fri Oct 28 2016 00:00:00 GMT+0300 (EEST),
Sat Oct 29 2016 00:00:00 GMT+0300 (EEST),
Sun Oct 30 2016 00:00:00 GMT+0300 (EEST)
];
var newCalendar = [];
var newMatchingDays = []
$.map(calendar, function(date){
newCalendar.push(date.toString())
});
$.map(matchingDays, function(date){
newMatchingDays.push(date.toString())
});
var result = [];
$.map(newCalendar, function (val, i) {
if ($.inArray(val, newMatchingDays) > -1) {
result.push(val);
}
});
console.log(result);

Firstly you can't compare dates like that, Date is an object.
eg.
var d1 = new Date('2016-09-30');
var d1 = new Date('2016-09-30');
console.log(d1 === d2); // = false
You would need to loop the array and compare each item, rather than use indexOf.
or maybe use the Array.filter(). Or alternatively use and object as a lookup.
eg. If say you had ->
var calendar = {
"Sun Oct 02 2016 00:00:00 GMT+0300 (EEST)": true,
"Sun Oct 09 2016 00:00:00 GMT+0300 (EEST)": true,
"Sun Oct 16 2016 00:00:00 GMT+0300 (EEST)": true,
"Sun Oct 23 2016 00:00:00 GMT+0300 (EEST)": true,
"Sun Oct 30 2016 00:00:00 GMT+0300 (EEST)": true
};
if (calendar["Sun Oct 16 2016 00:00:00 GMT+0300 (EEST)"]) {
console.log("We have date");
}
Notice how I use a string representation for the date, this could be a number too, eg. from Date.getTime().
Here is using Array.filter, I don't think it's as fast a Object lookup's. But here we go.
var calendar = [
new Date('2016-09-01'),
new Date('2016-09-12'),
new Date('2016-09-10')
];
var finddate = new Date('2016-09-12');
var found = calendar.filter(function (a) { return a.getTime() === finddate.getTime();});
And if you don't mind using third party library, try underscore..
eg.
var days = [new Date('2016-09-01'), new Date('2016-09-10'), new Date('2016-09-30')];
var finddays = [new Date('2016-09-01'), new Date('2016-09-30')];
var found = _.intersectionWith(days, finddays,
function (a,b) { return a.getTime() === b.getTime(); });

Related

How do I find the nearest Past or Future Date in an array of Dates by an DateObject?

Let's say we have an Array of Dates
var dateArr = [new Date("Thu Apr 01 2021 00:00:00 GMT+0200"), new Date("Sat May 01 2021 00:00:00 GMT+0200")];
and an Date Object, which we need to search in the dateArr, for example:
var findDate = new Date("Mon Apr 05 2021 07:50:06 GMT+0200");
And all together we have this PLUS
a function to return us the nearestDate in
dateArr by findDate which can lie in the past or future
var dateArr = [new Date("Thu Apr 01 2021 00:00:00 GMT+0200"), new Date("Sat May 01 2021 00:00:00 GMT+0200")];
var findDate = new Date("Mon Apr 05 2021 07:50:06 GMT+0200");
var result = getNearestDateInDateArrByFindDate(dateArr, findDate);
console.log(result); //should print to console: Thu Apr 01 2021 00:00:00 GMT+0200
function getNearestDateInDateArrByFindDate(dateArr, findDate) {
var nearestDateInPastOrFuture;
...
return nearestDateInPastOrFuture;
}
What I tried so far without sucess ...
var dateArr = [new Date("Thu Apr 01 2021 00:00:00 GMT+0200"), new Date("Sat May 01 2021 00:00:00 GMT+0200")];
var findDate = new Date("Mon Apr 05 2021 07:50:06 GMT+0200");
function getNearestDateInDateArrByFindDate(dateArr, findDate) {
console.log(dateArr);
console.log(findDate);
var nearestFutureDates = dateArr.filter(dt => dt.getTime() >= findDate.getTime());
var nearestFutureDates = nearestFutureDates.sort((a, b) => a.getTime() - b.getTime());
var nearestPastOrFutureDate = dateArr.filter(dt => dt.getTime() >= findDate.getTime());
var nearestPastOrFutureDate = nearestPastOrFutureDate.sort((a, b) => (findDate.getTime() - a.getTime()) - (findDate.getTime() - b.getTime()));
console.log(nearestFutureDates);
console.log(nearestPastOrFutureDate);
//returns always sat May 01 2021 00:00:00 GMT+0200
}
getNearestDateInDateArrByFindDate(dateArr, findDate)
And somehow the snippet doesn't return Apr 01 but rather April 31?
We can use Array.sort() to sort by the difference in ms from each date to findDate.
NB: We can get the absolute difference in milliseconds between two dates using
Math.abs(date1 - date2);
So we'll use this to sort like so:
var dateArr = [new Date("Thu Apr 01 2021 00:00:00 GMT+0200"), new Date("Sat May 01 2021 00:00:00 GMT+0200")];
var findDate = new Date("Mon Apr 05 2021 07:50:06 GMT+0200");
var result = getNearestDateInDateArrByFindDate(dateArr, findDate);
console.log(result); //should print to console: Thu Apr 01 2021 00:00:00 GMT+0200
function getNearestDateInDateArrByFindDate(dateArr, findDate) {
const sortedByDiff = [...dateArr].sort((a,b) => {
// Sort by the absolute difference in ms between dates.
return Math.abs(a - findDate) - Math.abs(b - findDate);
})
// Return the first date (the one with the smallest difference)
return sortedByDiff[0];
}
You can filter what is the nearest date on past and the nearest on future.
Optionally you can apply .sort((a, b) => a - b) to your array of dates if are not ordered.
const dateArr = [new Date("Thu Apr 01 2021 00:00:00 GMT+0200"), new Date("Sat May 01 2021 00:00:00 GMT+0200")].sort((a, b) => a - b);
const findDate = new Date("Mon Apr 05 2021 07:50:06 GMT+0200");
const nearestPastDate = (dateArr, date) => {
const pastArr = dateArr.filter(n => n <= date);
return pastArr.length > 0 ? pastArr[pastArr.length-1]: null;
};
const nearestFutureDate = (dateArr, date) => {
const futArr = dateArr.filter(n => n >= date);
return futArr.length > 0 ? futArr[0]: null;
};
console.log(dateArr);
console.log(nearestPastDate(dateArr, findDate));
console.log(nearestFutureDate(dateArr, findDate));

How to set time of javascript date object

I have two widgets. A calendar and a Time Widget.
My calendar is a DateTime object Wed Apr 29 2020 00:00:00 GMT-0400 and my time outputs this result 1:00 AM
I would like to Combine the two to make a new DateTime object. May I ask how about do I do that?
I tried this and it didn't work at all.
startDate.setTime(vm.startTime)
You need to iterate your Object entries and get values to combine them through an array.
mergeDateTime() {
const DateTime = {
a: "Wed Apr 29 2020 00:00:00 GMT-0400",
b: "1:00 AM",
};
const mergedDateTime = [];
for (let [key, value] of Object.entries(DateTime)) {
mergedDateTime.push(value);
}
return mergedDateTime;
}
I'm not sure but I think you want this.
I hope I've been helpful
var startDate = { Date :"Wed Apr 29 2020 00:00:00 GMT-0400" };
var startTime = { Time :"1:00 AM" };
var DateTime = Object.assign(startDate, startTime);
console.log(DateTime);
// { Date: 'Wed Apr 29 2020 00:00:00 GMT-0400', Time: '1:00 AM' }
Edit:
var startDate = { Date :"Wed Apr 29 2020 00:00:00 GMT-0400" };
var startTime = { Time :"1:00 AM" };
var DateTime = { DateAndTime: startDate.Date + " " + startTime.Time};
console.log(DateTime);
//{ DateAndTime: 'Wed Apr 29 2020 00:00:00 GMT-0400 1:00 AM' }
Try with splitting you time string and setting Hours value of your date object.
var startDate = "Wed Apr 29 2020 00:00:00 GMT-0400";
var startTime = "1:00 AM";
var result = new Date(startDate);
var hour = parseInt(startTime.split(":")[0]);
var minute = parseInt(startTime.split(":")[1].split(" ")[0]);
var amPmOffset = startTime.split(" ")[1] == "AM" ? 0 : 12;
result.setHours(hour, minute + amPmOffset, 0);
console.log(result.toString());

Difference between 2 dates, should work, but it isn't

i have got the following code which should simply tell me difference between 2 months, however all that it is returning is 1 and I can't figure it out!
function parseDate(str) {
function pad(s) { return (s < 10) ? '0' + s : s; }
var d = new Date(str);
return d;
}
Array.prototype.monthDifference = function() {
var months = this[1].getMonth() - this[0].getMonth() + (12 * (this[1].getFullYear() - this[0].getFullYear()));
if(this[1].getDate() < this[0].getDate()){
months--;
}
return months;
};
console.log([parseDate('01/01/2017'), parseDate('02/04/2017')].monthDifference());
Edit
Okay, see updated code below:
Array.prototype.monthDifference = function() {
console.log((this[1].getMonth()+1) - (this[0].getMonth()+1));
var months = (this[1].getMonth()+1) - (this[0].getMonth()+1) + (12 * (this[1].getFullYear() - this[0].getFullYear()));
if(this[1].getDate() < this[0].getDate()){
months--;
}
return (months > 1) ? 0 : months;
};
[pubDate, new Date()].monthDifference();
And now the output, how is one of the numbers negative and the other positive!? And comparing against today and dates in the past...
1
Sat Apr 27 1907 00:00:00 GMT+0100 (BST) Wed May 28 1902 00:00:00 GMT+0100 (BST)
-10
Wed Mar 26 1930 00:00:00 GMT+0000 (GMT) Wed May 28 1902 00:00:00 GMT+0100 (BST)
-10
Tue Mar 26 1929 00:00:00 GMT+0000 (GMT) Wed May 28 1902 00:00:00 GMT+0100 (BST)
-10
Tue Mar 26 1929 00:00:00 GMT+0000 (GMT) Wed May 28 1902 00:00:00 GMT+0100 (BST)
-1
Tue Jun 24 1913 00:00:00 GMT+0100 (BST) Wed May 28 1902 00:00:00 GMT+0100 (BST)
What about this ?
It gives days between two date.
Array.prototype.monthDifference = function() {
var b = this[0].getTime();
var x = this[1].getTime();
var y = x-b;
return Math.floor(y / (24*60*60*1000));
};
var a = [];
a.push(parseDate('01/01/2016'));
a.push(parseDate('02/04/2017'));
console.log(a.monthDifference());
The JavaScript Date constructor doesn't parse strings in UK format(dd/mm/yyyy).
You can split the date string and and then pass it into Date constructor.
Working fiddle: Date foramte fiddle
function formateDateToUK(dateString){
var splitDate = dateString.split('/'),
day = splitDate[0],
month = splitDate[1] - 1, //Javascript months are 0-11
year = splitDate[2],
formatedDate = new Date(year, month, day);
return formatedDate;
}
you functions returns '1', since it is the correct result :)
try:
console.log([parseDate('01/01/2017'), parseDate('07/01/2017')].monthDifference());
and it returns '6'... which is correct.
Note: 'new Date(str)' expects "MM/dd/yyyy" not "dd/MM/yyyy".
Hope this helps

creating a date range from 2 dates with linq.js and momentjs

I want to get all dates between a startDate and an endDate.
I wrap the startDate/endDate with moment() again to clone the start/endDate because they must not be changed.
But still the getDateRange gives me odd results about dates:
testCase.startDate = moment(new Date(2014, 0, 1));
testCase.endDate = moment(new Date(2014, 0, 27));
Although both dates are in 2014 I get a dateRange from december 2013 days?
Why is that?
function getDateRange(startDate, endDate) {
return Enumerable.range(0, moment(endDate).diff(moment(startDate), 'days') + 1)
.select(function (offset) {
return moment(startDate).add(offset, 'days')
})
.toArray();
}
UPDATE
Your query looks like it should work. Maybe you're interpreting the dates incorrectly. Remember, only the month starts at 0. Maybe you offset the year too when you looked at the values.
Here's an alternate way you can write the query:
function getDateRange(startDate, endDate) {
return Enumerable.Unfold(startDate, "moment($).add(1, 'd')")
.TakeWhile(function (d) { return d <= endDate; })
.ToArray();
}
Based on what I'm seeing in the comments, it appears you're using methods which mutates the dates. You'll either want to avoid using these methods or clone the date first and manipulate the clones.
// without cloning
var date1 = moment.utc([2014, 0, 1]);
console.log(String(date1)); // Wed Jan 01 2014 00:00:00 GMT+0000
var startOfDate1 = date1.startOf('week'); // mutated
console.log(String(date1)); // Sun Dec 29 2013 00:00:00 GMT+0000
// using moment()
var date2 = moment.utc([2014, 0, 1]);
console.log(String(date2)); // Wed Jan 01 2014 00:00:00 GMT+0000
var startOfDate2 = moment(date2).startOf('week'); // not mutated
console.log(String(date2)); // Wed Jan 01 2014 00:00:00 GMT+0000
// using clone()
var date3 = moment.utc([2014, 0, 1]);
console.log(String(date3)); // Wed Jan 01 2014 00:00:00 GMT+0000
var startOfDate3 = date3.clone().startOf('week'); // not mutated
console.log(String(date3)); // Wed Jan 01 2014 00:00:00 GMT+0000

Using a Date as the hash table key

How can I create a hash table object in JavaSript and use a date as the key? So far I've got this:
var eventHash = {};
for (var i = 0, l = events.length; i < l; i += 1) {
eventHash[events[i].date.getTime()] = events[i];
}
And then when I want to find the event associated with today I would use this:
var event = eventHash[(new Date(2011, 04, 26, 0, 0, 0, 0)).getTime()];
Can anyone see any pitfalls with this solution, or have any suggestions for improvement?
Why wouldn't you just use an ISO8601 representation of the date, so the key would be like 20110426. Creating a date object seems a bit inefficient.
It would also make debugging easier as the property names are more human readable, even if you add hhmmss also.
The only issue I see is that it's pretty limiting if you suddenly need to have multiple events with the same date. Otherwise it should be alright.
Also: Today is May 23, not Apr 26 :)
I have a somewhat similar problem and my solution may help others.
I have a list of "entries", each entry has a timestamp and a value.
I want to divide them up into "buckets", one for each day.
In Python I would have used collections.defaultdict but since JavaScript does not have something like that I do the following.
If you want to read the keys, remember that when you use a Date as an object key it gets converted as a string.
var get_entries = function() {
var entries = [];
entries.push({
'timestamp': 1381831606,
'value': 3
});
entries.push({
'timestamp': 1381831406,
'value': 2
});
entries.push({
'timestamp': 1381531606,
'value': 6
});
entries.push({
'timestamp': 1381221606,
'value': 9
});
entries.push({
'timestamp': 1381221601,
'value': 8
});
entries.push({
'timestamp': 1381221656,
'value': 7
});
return entries;
};
var normalize_date = function(timestamp) {
// JavaScript timestamps work with milliseconds.
var dt = new Date(timestamp * 1000);
return new Date(
dt.getFullYear(),
dt.getMonth(),
dt.getDate()
);
};
var prepare_data = function() {
var entry,
line = {};
var entries_raw = get_entries();
for (var i = 0; i < entries_raw.length; i++) {
entry = entries_raw[i];
entry.date = normalize_date(entries_raw[i].timestamp);
// If date not exists in line, create it.
console.log('Found entry for date', entry.date, 'with value', entry.value);
if (typeof(line[entry.date]) === 'undefined'){
line[entry.date] = 0;
}
line[entry.date] += entry.value;
}
console.log(line);
return line;
};
prepare_data();
Output:
$ nodejs diaryindex.js
Found entry for date Tue Oct 15 2013 00:00:00 GMT+0200 (CEST) with value 3
Found entry for date Tue Oct 15 2013 00:00:00 GMT+0200 (CEST) with value 2
Found entry for date Sat Oct 12 2013 00:00:00 GMT+0200 (CEST) with value 6
Found entry for date Tue Oct 08 2013 00:00:00 GMT+0200 (CEST) with value 9
Found entry for date Tue Oct 08 2013 00:00:00 GMT+0200 (CEST) with value 8
Found entry for date Tue Oct 08 2013 00:00:00 GMT+0200 (CEST) with value 7
{ 'Tue Oct 15 2013 00:00:00 GMT+0200 (CEST)': 5,
'Sat Oct 12 2013 00:00:00 GMT+0200 (CEST)': 6,
'Tue Oct 08 2013 00:00:00 GMT+0200 (CEST)': 24 }

Categories

Resources