Sorting dates including undefined and null - javascript

Im trying to sort data in order of ending soonest. this is my code and you can see the console results below. The sort is working somewhat but not completely. Can anyone help?
I see its to do with the invalid date but I can't work out how to get around this. The Invalid date field is blank in the JSON data that's pulled in. Null/undefined I would like to be last.
if (this.sortBy === "ending") {
filteredResults.sort((a, b) => {
var aDate = new Date(a.metaData.t);
var bDate = new Date(b.metaData.t);
console.log(b.metaData.t);
if (!aDate) {
aDate = 99999999; }
console.log("adate" + aDate);
if (!bDate) {
bDate = 99999999;
}
console.log("bdate" + bDate);
if (aDate > bDate) {
return 1;
}
if (aDate < bDate) {
return -1;
}
return 0;
});
}
return filteredResults;
},
Console.log data results
adateWed Nov 30 2022 00:00:00 GMT+0000 (Greenwich Mean Time)
bdateTue Dec 13 2022 00:00:00 GMT+0000 (Greenwich Mean Time)
adateWed Nov 30 2022 00:00:00 GMT+0000 (Greenwich Mean Time)
bdateFri Sep 09 2022 00:00:00 GMT+0100 (British Summer Time)
adateWed Nov 30 2022 00:00:00 GMT+0000 (Greenwich Mean Time)
bdateWed Nov 30 2022 00:00:00 GMT+0000 (Greenwich Mean Time)
adateWed Nov 30 2022 00:00:00 GMT+0000 (Greenwich Mean Time)
bdateThu Dec 08 2022 00:00:00 GMT+0000 (Greenwich Mean Time)
adateWed Nov 30 2022 00:00:00 GMT+0000 (Greenwich Mean Time)
bdateMon Dec 05 2022 00:00:00 GMT+0000 (Greenwich Mean Time)
adateInvalid Date
bdateTue Dec 13 2022 00:00:00 GMT+0000 (Greenwich Mean Time)
adateInvalid Date
bdateFri Mar 31 2023 00:00:00 GMT+0100 (British Summer Time)
adateInvalid Date
bdateSun Aug 20 2023 00:00:00 GMT+0100 (British Summer Time)
adateInvalid Date
bdateTue Jan 01 2030 00:00:00 GMT+0000 (Greenwich Mean Time)
adateInvalid Date
bdateTue Dec 13 2022 00:00:00 GMT+0000 (Greenwich Mean Time)
Invalid Date
Filtered results - the JSON is not exact here as its too big to add to this question. The format of the data is correct locally
(1 example I have XX most of the data for privacy reasons)
filteredResults {
K:"XX"
D:"XX"
N:"XX"
y:"XX"
t:"3 August 2022"
u:"XX"
X:"XX"
R:"XX"
T:"XX"
E:"XX"
}
.....
80 more rows like this but with various dates

You could check the value in advance and move unknown dates to the end of the array.
// assuming iso 8601 dates (same time zone or zulu), null or undefined
data.sort((a, b) =>
!a.date - !b.date ||
a.date.localeCompare(b.date)
);

Related

Code appears to be assigning when it should just be reading values

So I have this code:
var shotTime = this.lastShot;
shotTime.setMilliseconds(this.lastShot.getMilliseconds() + this.shootGrace);
console.log(shotTime);
console.log(new Date);
console.log(new Date()>shotTime);
console.log("-------------------------------");
if(new Date()>shotTime){
console.log("##############################");
this.lastShot = new Date();
}
This produces this output:
Mon Mar 12 2018 20:35:44 GMT+0000 (GMT Standard Time)
Mon Mar 12 2018 20:35:45 GMT+0000 (GMT Standard Time)
true
-------------------------------
##############################
Mon Mar 12 2018 20:35:45 GMT+0000 (GMT Standard Time)
Mon Mar 12 2018 20:35:45 GMT+0000 (GMT Standard Time)
false
-------------------------------
Mon Mar 12 2018 20:35:46 GMT+0000 (GMT Standard Time)
Mon Mar 12 2018 20:35:45 GMT+0000 (GMT Standard Time)
false
-------------------------------
Mon Mar 12 2018 20:35:46 GMT+0000 (GMT Standard Time)
Mon Mar 12 2018 20:35:46 GMT+0000 (GMT Standard Time)
false
-------------------------------
Mon Mar 12 2018 20:35:47 GMT+0000 (GMT Standard Time)
Mon Mar 12 2018 20:35:50 GMT+0000 (GMT Standard Time)
true
-------------------------------
##############################
This is rather odd as this.lastShot appears to be changing while false while it should only change when true. I can't figure out why there is this change.
Thanks,Ed.
shotTime = this.lastShot;
When you do this, you're not making a copy. You now have two references to the same Date object. Changing one of the references will now affect both. When you change shotTime, you're changing this.lastShot as well. Do this as a test:
var shotTime1 = new Date();
console.log(shotTime1.getMilliseconds());
var shotTime2 = shotTime1;
shotTime2.setMilliseconds(0);
console.log(shotTime1.getMilliseconds());
And you'll see the second one is zero because shotTime1 and shotTime2 both reference the same Date object.

please explain my error in this javascript date math

Here's the output from the Visual Studio Immediate Window. I start with mondaysDate, create a second date, thisDate, and then add integers to it using mondaysDate as the base.
I don't understand why adding 3 to the date yields November 2 and adding 4 to the date yields December 4th.
Is it illegal to invoke setDate() more than once?
?mondaysDate
Mon Oct 30 2017 00:00:00 GMT-0400 (Eastern Daylight Time)
?thisDate
Mon Oct 30 2017 00:00:00 GMT-0400 (Eastern Daylight Time)
?thisDate.setDate(mondaysDate.getDate() + 3)
1509595200000
?thisDate
Thu Nov 02 2017 00:00:00 GMT-0400 (Eastern Daylight Time)
?thisDate.setDate(mondaysDate.getDate() + 4)
1512363600000
?thisDate
Mon Dec 04 2017 00:00:00 GMT-0500 (Eastern Standard Time)
?mondaysDate
Mon Oct 30 2017 00:00:00 GMT-0400 (Eastern Daylight Time)
The issue is that first time you add 33 days from Oct 1, then you add 34 days from Nov 1.
thisDate.setDate(mondaysDate.getDate() + 3)
// You set the date to 30 + 3 (33) days from the first day of the current month (Oct 1)
// Oct 1 + 33 days = Nov 2
// thisDate = Thu Nov 02 2017 00:00:00 GMT-0400 (Eastern Daylight Time)
thisDate.setDate(mondaysDate.getDate() + 4)
// You set the date to 30 + 4 (34) days from the first day of the current month (Nov 1)
// Nov 1 + 34 days = Dec 4
// thisDate = Mon Dec 04 2017 00:00:00 GMT-0500 (Eastern Standard Time)
The date is set relative to thisDate, starting at 1st of the current month, and adds the day number in mondaysDate + 4 days. Every time you call setDate, you update thisDate.
You can read more about setDate on MDN.

How could I get the number of dates that fit a given month in a javascript array of momentjs dates?

I have a specific array of momentjs dates like this:
Schema:
tasks.data: [
{startDate: Mon Nov 25 2013 20:32:28 GMT-0500 (Eastern Standard Time)},
{startDate: Tue Nov 26 2013 20:32:28 GMT-0500 (Eastern Standard Time)},
{startDate: Wed Nov 27 2013 20:32:28 GMT-0500 (Eastern Standard Time)},
{startDate: Thu Nov 28 2013 20:32:28 GMT-0500 (Eastern Standard Time)},
{startDate: Fri Nov 29 2013 20:32:28 GMT-0500 (Eastern Standard Time)}
]
rest of the data..
Mon Nov 25 2013 20:32:28 GMT-0500 (Eastern Standard Time)
Tue Nov 26 2013 20:32:28 GMT-0500 (Eastern Standard Time)
Wed Nov 27 2013 20:32:28 GMT-0500 (Eastern Standard Time)
Thu Nov 28 2013 20:32:28 GMT-0500 (Eastern Standard Time)
Fri Nov 29 2013 20:32:28 GMT-0500 (Eastern Standard Time)
Sat Nov 30 2013 20:32:28 GMT-0500 (Eastern Standard Time)
Sun Dec 01 2013 20:32:28 GMT-0500 (Eastern Standard Time)
Mon Dec 02 2013 20:32:28 GMT-0500 (Eastern Standard Time)
Tue Dec 03 2013 20:32:28 GMT-0500 (Eastern Standard Time)
Wed Dec 04 2013 20:32:28 GMT-0500 (Eastern Standard Time)
Thu Dec 05 2013 20:32:28 GMT-0500 (Eastern Standard Time)
Fri Dec 06 2013 20:32:28 GMT-0500 (Eastern Standard Time)
Give say the Month of November 2013, how can I determine the count of dates that fall within that month and year? As my array has dates that span over 3 years.
My ultimate goal us to use the count in creating a sort of like gantt chart and use colspan="" on the month header based on the number of dates.
The information I have is the array of dates and the month and year I want to check.
Something like
return GetDateCounts(Month, Year){
return dateArry.map.indexOf(moment(startDate).month() == Month && moment(startDate).year() == Year)
}
Edit: with no duplicates.
Example:
If I have dates from Nov 21st-30th 2013, that should be count of 9, or 9 days.
If I have two repeating dates for the 21st, I would want to ignore that and only still have a count of 9.
Ok I managed out this convoluted function that works, but I'm sure there's got to be a better/fast, less lines of codes way to do this. Note I had to flatten my complex object cause I couldn't figure out how to loop through data.startDate, so I created a flat array of the dates in vm.dates.
If someone can come up with a better way I'll give the answer to them.
var uniqueDates = [];
var count = 0;
var unique = false;
vm.dates.forEach(function (date) {
if (moment(date).month() == month && moment(date).year() == year) {
unique = true;
//Attempt to find previous "day" in unique array list
uniqueDates.forEach(function (uniqueDate) {
if (moment(uniqueDate).date() == moment(date).date()) {
//If found set Unique to False
unique = false;
}
});
if (unique == true) {
//If Unique count
count++;
//and add found date to the Unique List
uniqueDates.push(date);
unique = false;
}
};
});
return count;

Finding difference between two arrays of Dates in JavaScript

I'm trying to find the difference between two Date arrays and then separate all different dates into another array of dates for later use. Also there is a little more functionality I want it to do. There is a variable diffDates. It should have to be an array because it can hold index of more than one months. With the help of that diffDates I want to populate selectDiffDates.
Please review this code to make it better and possibly faster and any ideas to implement the above mentioned last functionality in this piece of code. Thanks. Link to fiddle.
Array.prototype.diff = function(a) {
return this.filter(function(i) {
return (a.indexOf(i) < 0);
});
}
var monthIndex = [0,1,2,3,4,5,6,7,8,9,10,11];
var dMarked=[], dFiltered=[], selectDiffDates = [];
dMarked=["Thu Jan 01 2015 00:00:00 GMT+0500 (Pakistan Standard Time)",
"Thu Feb 05 2015 00:00:00 GMT+0500 (Pakistan Standard Time)",
"Thu Mar 05 2015 00:00:00 GMT+0500 (Pakistan Standard Time)",
"Thu Apr 02 2015 00:00:00 GMT+0500 (Pakistan Standard Time)",
"Thu Jun 04 2015 00:00:00 GMT+0500 (Pakistan Standard Time)",
"Thu Jan 01 2015 00:00:00 GMT+0500 (Pakistan Standard Time)"];
dFiltered=["Thu Jan 08 2015 00:00:00 GMT+0500 (Pakistan Standard Time)",
"Thu Feb 12 2015 00:00:00 GMT+0500 (Pakistan Standard Time)",
"Thu Mar 12 2015 00:00:00 GMT+0500 (Pakistan Standard Time)",
"Thu Apr 09 2015 00:00:00 GMT+0500 (Pakistan Standard Time)",
"Thu May 07 2015 00:00:00 GMT+0500 (Pakistan Standard Time)",
"Thu Jun 11 2015 00:00:00 GMT+0500 (Pakistan Standard Time)"];
var dMarkedMonths = [], dFilteredMonths = [];
for(var i=0; i<dMarked.length; i++){
dMarkedMonths.push( monthIndex[new Date(dMarked[i]).getMonth()]);
}
for(var i=0; i<dFiltered.length; i++){
dFilteredMonths.push( monthIndex[new Date(dFiltered[i]).getMonth()]);
}
console.log(dMarkedMonths);
console.log(dFilteredMonths);
var diffDates = dFilteredMonths.diff( dMarkedMonths );
console.log("Difference: "+diffDates);
for(var d=0; d<dFiltered.length; d++){
if(new Date(dFiltered[d]).getMonth() == diffDates){
selectDiffDates.push(dFiltered[d]);
}
}
console.log(selectDiffDates);
$("#console").html(selectDiffDates);
diffDates is an array, so you should not compare an array with single month...rather you should check if month exists in the diffDates array:
for(var d=0; d<dFiltered.length; d++){
if(diffDates.indexOf(new Date(dFiltered[d]).getMonth())>-1){
selectDiffDates.push(dFiltered[d]);
}
}
On the performance part: please check the updated fiddle http://jsfiddle.net/q7rmr5uq/3/
Your current logic does not follow your requirement. Currently you are picking months and finding different months and then making the dates again from the months you got. But this would skip all those dates who has same month but different day or year.
The better approach for your requirement should include finding the difference between two dates rather than two months.

Using Moment.js to make an array of this week's dates doesn't add to array

I'm using Moment.js to make a Resource Calendar and I need an array of dates for this week. The console log of my current function prints out appropriately but the array that gets pushed in for each date is wrong.
var startOfWeek = moment().startOf('week');
var endOfWeek = moment().endOf('week');
var days = [];
var day = startOfWeek;
do {
console.log(day._d);
days.push(day._d);
day = day.add(1, 'd');
}
while (day <= endOfWeek);
console.log(days);
Returns:
Sun Jan 18 2015 00:00:00 GMT-0500 (EST) schedule.js?320233fd69f9859ccb55248b608e15891032b17d:31
Mon Jan 19 2015 00:00:00 GMT-0500 (EST) schedule.js?320233fd69f9859ccb55248b608e15891032b17d:31
Tue Jan 20 2015 00:00:00 GMT-0500 (EST) schedule.js?320233fd69f9859ccb55248b608e15891032b17d:31
Wed Jan 21 2015 00:00:00 GMT-0500 (EST) schedule.js?320233fd69f9859ccb55248b608e15891032b17d:31
Thu Jan 22 2015 00:00:00 GMT-0500 (EST) schedule.js?320233fd69f9859ccb55248b608e15891032b17d:31
Fri Jan 23 2015 00:00:00 GMT-0500 (EST) schedule.js?320233fd69f9859ccb55248b608e15891032b17d:31
Sat Jan 24 2015 00:00:00 GMT-0500 (EST) schedule.js?320233fd69f9859ccb55248b608e15891032b17d:31
[Sun Jan 25 2015 00:00:00 GMT-0500 (EST), Sun Jan 25 2015 00:00:00 GMT-0500 (EST), Sun Jan 25 2015 00:00:00 GMT-0500 (EST), Sun Jan 25 2015 00:00:00 GMT-0500 (EST), Sun Jan 25 2015 00:00:00 GMT-0500 (EST), Sun Jan 25 2015 00:00:00 GMT-0500 (EST), Sun Jan 25 2015 00:00:00 GMT-0500 (EST)]
Notice how the array at the bottom is the next date in the array repeated 7 times.
As danludwig mentioned in his comment on the question, you are adding a reference for the same date to the array multiple times.
From the Moment.js documentation:
It should be noted that moments are mutable. Calling any of the manipulation methods will change the original moment.
If you want to create a copy and manipulate it, you should use moment#clone before manipulating the moment.
You should be calling the clone function on the Moment date object as shown here.
var startOfWeek = moment().startOf('week');
var endOfWeek = moment().endOf('week');
var days = [];
var day = startOfWeek;
while (day <= endOfWeek) {
days.push(day.toDate());
day = day.clone().add(1, 'd');
}
console.log(days);
As an aside:
You should not reference internal fields/functions of a 3rd party library. The name of these references are more likely to change than the public API described in the documentation. _d can be referenced by calling the public function toDate.

Categories