2

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"
    }
]
6
  • 1
    where do you want to sort items with no or corrupt date? Commented Jun 15, 2019 at 16:47
  • order by date descending and the ones with no corrupt data should go at the beginning of the array Commented Jun 15, 2019 at 16:55
  • btw, sort sorts the array. an assignment takes just the same object reference. Commented Jun 15, 2019 at 16:56
  • a - b gives ascending order. Do you really mean descending? Commented Jun 15, 2019 at 16:59
  • is getTime a method of date property? please add some data to proof the algorithms of the answers. if your callback works, why do you get a descending result by using the delta of a and b? please add the wanted result as well to the question (and not in comment section). Commented Jun 15, 2019 at 18:50

7 Answers 7

5

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 Dates to be at the bottom, then your sorting function should treat these Invalid Dates 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 Dates are sorted at the bottom of your array.

Sign up to request clarification or add additional context in comments.

Comments

2

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; }

1 Comment

right, it needs an check to prevent the call of the function for not given functions.
1

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)

Comments

0

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);

2 Comments

let sorted = data.sort(...) is slightly misleading. data.sort(...) sorts data in place. sorted is not a copy of the data, but simply another reference to the same array.
Removed sorted, force of habit, I mostly keep seperate variables so I can track the flow of data.
-1

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)

7 Comments

Your comparison function doesn't always return a positive/negative/zero number as required by sort.
Now it returns inconsistent results. It's not a valid comparator.
Also, according to OP, a.date is undefined, not a
You can edit the answer, I tried to consider all the comments
It's not transitive. Imagine you have three elements, a with a date of 2000-01-01, b with a date of null, c with a date of 2000-12-31. Then your comparison function says that a == b, b == c, but a < c. That's not valid (it violates the transitivity requirement).
|
-2

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
});

4 Comments

Your comparison function doesn't always return a positive/negative/zero number as required by sort.
Now it returns inconsistent results. It's not a valid comparator.
@melpomene Sorry can't get what you mean.
It's not transitive. Imagine you have three elements, a with a date of 2000-01-01, b with a date of null, c with a date of 2000-12-31. Then your comparison function says that a == b, b == c, but a < c. That's not valid (it violates the transitivity requirement).
-2

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);

7 Comments

Imagine you have three elements, a with a date of 2000-01-01, b with a date of null, c with a date of 2000-12-31. Then your comparison function says that a == b, b == c, but a < c. That's not valid (it violates the transitivity requirement).
@melpomene in that case we can simply filter the falsy value and than sort them ( updated ), i am not how the OP wants the falsy values to be treated
@CodeManiac this causes data loss of objects without date field;
As per OPs comment, he wants the data order by date descending and the ones with no corrupt data should go at the beginning of the array
@AyushGupta it's no where mentioned in question to keep the invalid data at start of array
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.