In our angularjs app we're receiving an array of dates that then need to be filtered out to only return an array full of unique dates (not strings). I tried some of the answers on SO but I think because I'm comparing dates and not strings - I'm yielding different results. Any help on what the best approach is would be very helpful.
Asked
Active
Viewed 2,626 times
2

chris
- 1,152
- 1
- 15
- 37
2 Answers
3
You are right, date equality is different from string equality. Dates are objects, and the ===
comparator for objects compares them by reference, not value. Since {} === {}
in JS is false
, two Dates will never be equal to each other. So, let's just turn the dates into numbers:
let dates = [new Date(), new Date('1/1/11'), new Date('1/1/11'), new Date('1/4/66')]
let uniqueDates = dates
.map(s => s.getTime())
.filter((s, i, a) => a.indexOf(s) == i)
.map(s => new Date(s));
console.log(uniqueDates);
The logic with indexOf
is that every unique value should be present only at its own position; any others are duplicates (s is current item, i is current index, and a is the array itself). Then we map the array back into Dates
and return it.

joh04667
- 7,159
- 27
- 34
-
1thank you - the refactor of your code was the cherry on top. I think I was overcomplicating before by dismissing the idea of converting to a string and then back to date – chris May 17 '17 at 23:11
-
1No problem! Come to think of it, it's more straightforward to replace `.toString()` with `.getTime()`. That returns the date as a simple number, epoch time. Cleaner and a little more efficient than comparing strings. – joh04667 May 17 '17 at 23:22
3
If you're using lodash:
const date1 = new Date();
const date2 = new Date();
const arr = [date1, date1, date2, date2];
const uniqueDates = _.uniqBy(arr, date => date.getTime());
Uses uniqBy
to ensure that we compare dates by their value and not just by object identity. See here: Compare two dates with JavaScript