Reputation: 2402
I´m using sort() to order an Array by date
elements = data.sort(function(a, b) {
return a.date.getTime() - b.date.getTime()
});
the problem is that some elements are missing the date (or the date is invalid) and that´s causing this error:
Cannot read property 'getTime' of undefined
update: I have moment ready to use
Where should I check if date is valid date and then use it to order the array?
update: this is the data I have
[{
"date": "2019-06-15 14:57:13",
"user": "john"
},
{
"date": "2019-06-15 05:48:01",
"user": "mike"
},
{
"date": "bad-date-format",
"user": "donna"
},
{
"date": "2019-06-08 10:45:09",
"user": "Ismil"
},
{
"date": "",
"user": "Daniel17"
}
]
and this is the output I expect
[
{
"date": "2019-06-15 14:57:13",
"user": "john"
},
{
"date": "2019-06-15 05:48:01",
"user": "mike"
},
{
"date": "2019-06-08 10:45:09",
"user": "Ismil"
},
{
"date": "bad-date-format",
"user": "donna"
},
{
"date": "",
"user": "Daniel17"
}
]
Upvotes: 2
Views: 2162
Reputation: 820
You don't have to check if the string is a valid date.
Here's a working code:
const data = [{
"date": "2019-06-15 14:57:13",
"user": "john"
},
{
"date": "2019-06-15 05:48:01",
"user": "mike"
},
{
"date": "bad-date-format",
"user": "donna"
},
{
"date": "2019-06-08 10:45:09",
"user": "Ismil"
},
{
"date": "",
"user": "Daniel17"
}
];
const elements = data.sort((a, b) => (new Date(b.date).getTime() || -Infinity) - (new Date(a.date).getTime() || -Infinity));
console.log(elements);
The trick behind the above code is that new Date()
will give an Invalid Date
object if you pass an invalid date string to it, which will return NaN
if you executed its getTime()
method.
Now because you want all Invalid Date
s to be at the bottom, then your sorting function should treat these Invalid Date
s as the lowest rated in your array, and that's what -Infinite
means (the lowest number. If you add any number to it will lead to -Infinite
).
I assume that it doesn't matter how Invalid Date
s are sorted at the bottom of your array.
Upvotes: 5
Reputation: 386550
You could check if the property exists has the wanted format and then sort the date by string descending and if one has no valid format, take the delta of the boolean values.
function checkDate(string) {
return typeof string === 'string'
&& /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(string);
}
var array = [{ date: "2019-06-15 14:57:13", user: "john" }, { date: "2019-06-15 05:48:01", user: "mike" }, { date: "bad-date-format", user: "donna" }, { date: "2019-06-08 10:45:09", user: "Ismil" }, { date: "", user: "Daniel17" }];
array.sort((a, b) => {
var aC = checkDate(a.date),
bC = checkDate(b.date);
return aC && bC
? b.date.localeCompare(a.date)
: bC - aC;
});
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2
Reputation: 18515
You can use Date.parse
to make sure you have a valid date and when you do for both of your parameters sort them. Otherwise sort the one with the valid date "higher":
let data = [{ "date": "2019-06-15 14:57:13", "user": "john" }, { "date": "2019-06-15 05:48:01", "user": "mike" }, { "date": "bad-date-format", "user": "donna" }, { "date": "2019-06-08 10:45:09", "user": "Ismil" }, { "date": "", "user": "Daniel17" } ]
let result = data.sort((a,b) => Date.parse(a.date) && Date.parse(b.date)
? new Date(b.date).getTime() - new Date(a.date).getTime()
: Date.parse(a.date) ? -1 : 0
)
console.log(result)
Upvotes: 1
Reputation: 5121
data.sort(function(a, b) {
if (typeof a.date !== 'undefined' && typeof b.date !== 'undefined') {
return a.date.getTime() - b.date.getTime()
}
return 0
});
Working simple example
data = [{date:"100"},{date:null},{date:"1"}, {nodate:"10"}];
data.sort(function(a, b) {
if (typeof a.date !== 'undefined' && typeof b.date !== 'undefined') {
return a.date - b.date
}
return 0
});
console.log(data)
Upvotes: -1
Reputation: 37755
You can check before using getTime
let data = [{
date: new Date('2019-01-03T00:00:00.000Z')
},{
date: new Date('2020-01-03T00:00:00.000Z')
},{
date: new Date('2018-01-03T00:00:00.000Z')
}, {}]
data.sort((a, b)=>{
if(!isNaN(new Date(a.date).getTime()) && !isNaN(new Date(b.date).getTime())){
return a.date.getTime() - b.date.getTime()
}
return Infinity
});
console.log(data);
Upvotes: -2
Reputation: 9285
As per OPs comment
order by date descending and the ones with no corrupt data should go at the beginning of the array
let data = [{
date: new Date('2019-01-03T00:00:00.000Z')
},{
date: new Date('2020-01-03T00:00:00.000Z')
},{
date: new Date('2018-01-03T00:00:00.000Z')
}, {}]
function safeGetTime(obj) {
if (obj && obj.date && obj.date.getTime) {
return obj.date.getTime();
}
return Number.MAX_SAFE_INTEGER; // replace with `return 0` to put invalid data at end of array
}
data.sort(function(a, b) {
return safeGetTime(b) - safeGetTime(a)
});
console.log(data);
Upvotes: 0
Reputation: 36564
You can use &&
operator.
data.sort(function(a, b) {
return (a.date && b.date && a.date.getTime && b.date.getTime && a.date.getTime() - b.date.getTime()) || 0
});
I would prefer an helper function.
const validDate = (...arr) => arr.every(x => x.date && x.date.getTime);
data.sort(function(a, b) {
return (validDate(a,b) && a.date.getTime() - b.date.getTime()) || 0
});
Upvotes: -2