Search code examples
javascriptnode.jstimestampmomentjslodash

How to group data into arrays by intervals


So I have a large data array with objects looking like this:

Row {
  month_year_index: 'september_2019_2',
  localcol: 2019-09-13T00:52:16.847Z,
  datamap: {
    Curr1_mA: 769,
    Curr2_mA: 139,
    Curr3_mA: 0,
    P1_W: 75,
    P2_W: 0,
    P3_W: 0,
    P_Total_W: 75,
    U1N_Vx10: 2261,
    U2N_Vx10: 2330,
    U3N_Vx10: 2360
  }
}

Using the following code I managed to group all the data by day using lodash groupBy function and momentjs which is what I wanted and it's stored in an array of arrays with each array having all the objects with the timestamp (called localcol) that have the same day.

queryAllPartitions().then((rowResults) => {
    console.log('Final Row Length', rowResults.length);

    let byDay = _.groupBy(rowResults, (result) => moment(result['localcol'], 'DD/MM/YYYY').startOf('day'));

    const groupInterval = 900000 // 15 min
    let byTimePeriod = [];

    const result = []
    for (let i = 0; i < Object.entries(byDay).length; i++) { // 30
        console.log("day", i)

        byTimePeriod[i] = []
        byTimePeriod[i] = _.groupBy((Object.entries(byDay)[i][1]), (result) => moment(result['localcol'], 'DD/MM/YYYY').startOf('minute'));
    }
}

My problem is that I have to group them yet again by a certain time like this:

  • 1 minute = 60000 ms
  • 5 minutes = 300000 ms
  • 15 minutes = 900000 ms
  • 1 hour = 3600000 ms

I can group them by minute and hour using lodash and momentjs with the following lines:

byTimePeriod[i] = _.groupBy((Object.entries(byDay)[i][1]), (result) => moment(result['localcol'], 'DD/MM/YYYY').startOf('minute'));

OR

byTimePeriod[i] = _.groupBy((Object.entries(byDay)[i][1]), (result) => moment(result['localcol'], 'DD/MM/YYYY').startOf('hour'));

But I can't figure out how to do it for the other 2(5 min and 15 min). I've looked around the docs on momentjs: https://momentjscom.readthedocs.io/en/latest/moment/03-manipulating/03-start-of/ but after trying for a lot of time I think that it might not be possible using startof and I have to group them using a different approach.


Solution

  • Essentially the startOf function set to zero the specified date fields.

    For grouping by 5 minutes you must get the current minutes and check if they are on the correct interval, to do this you get the current minutes / 5 * 5.

    Replace 5 with 15 for 15 minutes.

    Obviously this work starting interval from 0:

    • 0-4 = 0
    • 5-9 = 5

    and so on

    (result) => moment(result['localcol'], 'DD/MM/YYYY').minutes(Math.floor(moment(result['localcol'], 'DD/MM/YYYY').minutes() / 5) * 5);;
    moment(date, 'DD/MM/YYYY').minutes(minutes);