0

Lets say i have an array of objects which features a start and end date:

var events = [
    {start: '2021-01-25 10:00:00', end: '2021-01-25 11:00:00', title: 'Event #1'},
    {start: '2021-01-25 10:00:00', end: '2021-01-25 12:00:00', title: 'Event #2'},
    {start: '2021-01-25 18:00:00', end: '2021-01-25 19:00:00', title: 'Event #3'},
    {start: '2021-01-25 19:00:00', end: '2021-01-25 20:00:00', title: 'Event #4'},
    {start: '2021-01-25 19:30:00', end: '2021-01-25 20:30:00', title: 'Event #5'},
    {start: '2021-01-25 23:00:00', end: '2021-01-25 23:30:00', title: 'Event #6'},
]

As you can see, the time ranges might partially overlap between records. The dates are Date objects.

I want to group these records into smaller groups, where each group is at least X hours apart. Lets say the gap is 5 hours, in that case my expected result would be this:

var event_groups = [
    [
        {start: '2021-01-25 10:00:00', end: '2021-01-25 11:00:00', title: 'Event #1'},
        {start: '2021-01-25 10:00:00', end: '2021-01-25 12:00:00', title: 'Event #2'},
    ],
    [
        {start: '2021-01-25 18:00:00', end: '2021-01-25 19:00:00', title: 'Event #3'},
        {start: '2021-01-25 19:00:00', end: '2021-01-25 20:00:00', title: 'Event #4'},
        {start: '2021-01-25 19:30:00', end: '2021-01-25 20:30:00', title: 'Event #5'},
        {start: '2021-01-25 23:00:00', end: '2021-01-25 23:30:00', title: 'Event #6'},
    ]
]

If the gap is 2 hours, the results would change like this:

var event_groups = [
    [
        {start: '2021-01-25 10:00:00', end: '2021-01-25 11:00:00', title: 'Event #1'},
        {start: '2021-01-25 10:00:00', end: '2021-01-25 12:00:00', title: 'Event #2'},
    ],
    [
        {start: '2021-01-25 18:00:00', end: '2021-01-25 19:00:00', title: 'Event #3'},
        {start: '2021-01-25 19:00:00', end: '2021-01-25 20:00:00', title: 'Event #4'},
        {start: '2021-01-25 19:30:00', end: '2021-01-25 20:30:00', title: 'Event #5'},
    ],
    [
        {start: '2021-01-25 23:00:00', end: '2021-01-25 23:30:00', title: 'Event #6'},
    ]
]

As for where i'm standing so far with my code(its not much...)

var event_groups = [];
var event_group = [];
events.forEach(function(event){
    
  //If its an empty group, just add the data and move forward
    if(!event_group.length) {
    event_group.push(event);
    continue;
  }

})

Any ideas how should i solve this problem?

passatgt
  • 4,234
  • 4
  • 40
  • 54
  • are they already sorted ? – Mister Jojo Jan 26 '21 at 15:09
  • this is unclear; how to compute the gap ? beetwenn group on first start and group last start or first start and group last end, or first end and group last start ? – Mister Jojo Jan 26 '21 at 15:18
  • You mean i should sort the records based on the start date first? It should be in order, but not sorted by me, so this is the raw data. – passatgt Jan 26 '21 at 15:20
  • @MisterJojo a group's latest end date and another group's earliest start date needs to be at least X hours apart. Does that makes sense? – passatgt Jan 26 '21 at 15:21
  • no, in you hours group part , there is 2h30 beetwen latest end date = 20:30:00 and earliest start date = 18:00:00 – Mister Jojo Jan 26 '21 at 16:10

1 Answers1

0

You could get the delta of time and check against the wanted length for building a new group.

const
    group = (array, hours) => array.reduce((r, o) => {
        if (!r.length || o.start - r[r.length - 1][0].start > hours * 1000 * 60 * 60) r.push([o]);
        else r[r.length - 1].push(o);
        return r;
    }, []),
    events = [{ start: '2021-01-25 10:00:00', end: '2021-01-25 11:00:00', title: 'Event #1' }, { start: '2021-01-25 10:00:00', end: '2021-01-25 12:00:00', title: 'Event #2' }, { start: '2021-01-25 18:00:00', end: '2021-01-25 19:00:00', title: 'Event #3' }, { start: '2021-01-25 19:00:00', end: '2021-01-25 20:00:00', title: 'Event #4' }, { start: '2021-01-25 19:30:00', end: '2021-01-25 20:30:00', title: 'Event #5' }, { start: '2021-01-25 23:00:00', end: '2021-01-25 23:30:00', title: 'Event #6' }]
        .map(o => ({ ...o, start: new Date(o.start), end: new Date(o.end) }));

console.log(group(events, 5));
console.log(group(events, 2));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • I just get `"start": null, "end": null,` for all events. Using the built–in parser as in `new Date(o.start)` is not a good idea, see [*Why does Date.parse give incorrect results?*](https://stackoverflow.com/questions/2587345/why-does-date-parse-give-incorrect-results) – RobG Jan 26 '21 at 23:02
  • @RobG, op states, the dates in data are `Date` objects, but thank you for the hint. – Nina Scholz Jan 27 '21 at 07:29
  • Yeah, but one person's Date is another person's timestamp. ;-) – RobG Jan 27 '21 at 22:12