1

What I want?

Form groups of dates that are consecutive.

What consecutive means?

15-05-2020, 16-05-2020, 17-05-2020...

How we group them?

[
  [4114696980000,4114783380000,4114869780000],
  [4120485780000,4120572180000,4120658580000,4120744980000]
]

So in each array we have groups of dates that are consecutive.

What dates are not consecutive?

26-05-2020 and 28-05-2020 because after day 26, the next one is 27-05-2020, so we would obtain two arrays, one for 26-05-2020 and other for 28-05-2020.

Do I have a function to do that? Yes.

Is that function working? No.

Why? All my days are consecutive, but it gives me two arrays (groups) and I cant get why It does that.

CODE:

var arr = [4128175380000,4128261780000,4128348180000,
           4128434580000,4128520980000,4128607380000,
           4128697380000,4128783780000,4128870180000],

i = 0,
result = arr.reduce(function(stack, b) {
      var cur = stack[i],
          a = cur ? cur[cur.length-1] : 0;

      if (b - a > 86400000) {
          i++;
      }

      if (!stack[i])
          stack[i] = [];

      stack[i].push(b);

      return stack;
}, []);

console.log(result);

The result should be just one array with all dates because they are consecutive..

Lets clarify consecutive days with this snippet converting the dates to readable form:

var arr = [4128175380000,4128261780000,4128348180000,
           4128434580000,4128520980000,4128607380000,
           4128697380000,4128783780000,4128870180000];
           
 function getStringDatesFormat(arr) {
    for (var i=0; i < arr.length; i++) {
    console.log(new Date(arr[i]).toDateString());
  }
 }
 getStringDatesFormat(arr);

As you can see in the results, all the days are consecutive, there is no day left between so why it breaks them into two arrays the above function code?

Edit: Output from the above

Mon Oct 25 2100 20:23:00 GMT+0100 (British Summer Time)
Tue Oct 26 2100 20:23:00 GMT+0100 (British Summer Time)
Wed Oct 27 2100 20:23:00 GMT+0100 (British Summer Time)
Thu Oct 28 2100 20:23:00 GMT+0100 (British Summer Time)
Fri Oct 29 2100 20:23:00 GMT+0100 (British Summer Time)
Sat Oct 30 2100 20:23:00 GMT+0100 (British Summer Time)
Sun Oct 31 2100 20:23:00 GMT+0000 (Greenwich Mean Time)
Mon Nov 01 2100 20:23:00 GMT+0000 (Greenwich Mean Time)
Tue Nov 02 2100 20:23:00 GMT+0000 (Greenwich Mean Time)
freedomn-m
  • 27,664
  • 8
  • 35
  • 57
Amos Isaila
  • 286
  • 3
  • 14
  • 1
    Does consecutive here mean simply in the numerical sense, or do they also have to be positioned consecutively in the array to be considered consecutive? `[1, 2, 4, 3]` Are these one consecutive group? or is only `[1, 2]` consecutive? – GirkovArpa Sep 10 '20 at 09:10
  • Not in the numerical sense, but in the date sense. I want day 1, 2 and 3 to be in one array, and 5, 6, 7 in other. This is because we dont have day 4 so it breaks into two arrays with consecutive days both. – Amos Isaila Sep 10 '20 at 09:45
  • Why does it happen? See `console.log(4128697380000 - 4128607380000)` – freedomn-m Sep 10 '20 at 09:47
  • try `arr.forEach(a=> console.log(new Date(a)))` you will find out the reason. pointed out by @freedomn-m and @domenikk `4128697380000 - 4128607380000 = 90000000` – Sheelpriy Sep 10 '20 at 09:49
  • 1
    So why are those two dates 90000000 and not 86400000? I've taken the liberty of adding the *actual* output of your debug-dump (not the snippet output). Should now be obvious why Sat Oct 30 23:00 and Sun Oct 31 23:00 **are 25 hours apart**. – freedomn-m Sep 10 '20 at 09:58
  • 2
    You're not checking if they're consecutive *days*, you're checking if they're more than *24 hours apart* - which those two dates+times are as there's 25 hours in between those dates. Same as there's 23 hours between the last Sat/Sun in March... – freedomn-m Sep 10 '20 at 10:01
  • Thats true. So I should use a library such as momentjs with isAfter as described below? – Amos Isaila Sep 10 '20 at 10:03
  • No need for a library, you can convert to date (which the library will do anyway) and check with .AddDay (eg https://stackoverflow.com/a/563442/2181514) – freedomn-m Sep 10 '20 at 10:04
  • I used @domenikk above answer. Can you post the solution with AddDay? Thank you. – Amos Isaila Sep 11 '20 at 08:08

2 Answers2

1

Given your definition of consecutive and the dates you've provided, it is expected that your function is creating two child arrays.

4128697380000 - 4128607380000 = 90000000

Since this is greater than 86400000, these days aren't consecutive (according to your condition).

If you convert them to dates, they are indeed consecutive; but as points in time they're separated by more than 86400000 milliseconds.

To get the results you expect, you need to convert them to dates first and check if they are consecutive. For that you can use a library like date-fns or momentjs.

For example, with date-fns you could check for consecutive dates like this:

if(isAfter(b, a)) {
    i++;
}

Assuming you've already mapped the values to dates using fromUnixTime

domenikk
  • 1,723
  • 1
  • 10
  • 12
0

Your question is basically, how does one group numbers from a list by whether they are consecutive to one another?

It's ambiguous exactly what you mean by consecutive; assuming you mean consecutive on the number line as opposed to in the array, this will work. Note there is nothing special about dates. It will work for all numbers.

const numbers = [123, 124, 0, 125, 1, 2, 4, 6, 2, 9, 10, 11, 14];

const groups = numbers.reduce((groups, number, i) => {
  const group = groups.find((group) => group.find((n) => Math.abs(n - number) === 1));
  group ? group.push(number) : groups.push([number]);
  return (i === numbers.length - 1)
    ? groups
      .map((g) => g.sort((a, b) => a - b))
      .sort(([a], [b]) => a - b)
    : groups;
}, []);

console.log(groups);
GirkovArpa
  • 4,427
  • 4
  • 14
  • 43