Is there an efficient solution to group an array of dates into objects and subarrays grouped by day?
Example:
groupDatesByDay([
new Date('2020-01-01 00:00:00'),
new Date('2020-01-01 00:00:01'),
new Date('2020-01-02 00:00:00'),
new Date('2020-01-02 00:00:01'),
new Date('2020-01-03 00:00:00'),
new Date('2020-01-03 00:00:01'),
])
The expected return value is the following, where there's an Object for each day with a key day
representing the start of the day and an array containing all dates that are on the respective day.
I am using Date-Fns' startOfDay()
method.
[
{
day: Date Wed Jan 01 2020 00:00:00 GMT+0100 (Central European Standard Time),
times: [
Date Wed Jan 01 2020 00:00:00 GMT+0100 (Central European Standard Time),
Date Wed Jan 01 2020 00:00:01 GMT+0100 (Central European Standard Time),
]
},
{
day: Date Thu Jan 02 2020 00:00:00 GMT+0100 (Central European Standard Time),
times: [
Date Wed Jan 02 2020 00:00:00 GMT+0100 (Central European Standard Time),
Date Wed Jan 02 2020 00:00:01 GMT+0100 (Central European Standard Time),
]
},
{
day: Date Fri Jan 03 2020 00:00:00 GMT+0100 (Central European Standard Time),
times: [
Date Wed Jan 03 2020 00:00:00 GMT+0100 (Central European Standard Time),
Date Wed Jan 03 2020 00:00:01 GMT+0100 (Central European Standard Time),
]
},
]
I wrote a function that works, but the time complexity is really bad. Can this be done (much) better?
groupDatesByDay(dates) {
let grouped = []
//Push first date to grouped
grouped.push({
day: startOfDay(dates[0]),
times: [dates[0]]
})
//Iterate dates
dates.forEach((date, inx) => {
if (inx == 0) {
return
}
let found = false
for (let i=0; i<grouped.length; i++) {
//Check if grouped contains day of date already
if (grouped[i].day.getTime() == startOfDay(date).getTime()) {
grouped[i].times.push(date)
found = true
break
}
}
if (found) {
return
} else {
grouped.push({
day: startOfDay(date),
times: [date]
})
}
});
return grouped
}