0

I have an array like this,

[
 {id: 1, name: "sleep", endTime: 1600261550535, startTime: 1600261541729}, // 9 sec
 {id: 2, name: "sleep", endTime: 1600261527833, startTime: 1600261522709}, // 5 sec 
 {id: 3, name: "sleep", endTime: 1600261496881, startTime: 1600261437616}, // 59 sec 
 {id: 4, name: "awake", endTime: 1600261427129, startTime: 1600261413596}, // 14 sec 
 {id: 5, name: "awake", endTime: 1600261403114, startTime: 1600261347569}, // 56 sec 
 {id: 6, name: "awake", endTime: 1600261337893, startTime: 1600261206497}, // 2 min 11 sec 
]

I need to work out the the total time(duration) when all of the object with the same name are added together. The time format should be in hr, min, sec. Obviously it's easy to get the duration of one of them at a time but I cant think a way to add up duration of together.

Help is much appreciated. Thanks. Feel free to use moment or lodash

Output should be

total duration sleep : 1 min 13 secs
total duration awake : 3 min 21 secs

Edit: Thank you all so much for your response, You guys are what makes the community better.

Jereme
  • 427
  • 7
  • 15
  • 1
    What did you try so far? – NikNik Sep 16 '20 at 13:45
  • Does this answer your question? [JavaScript - Get minutes between two dates](https://stackoverflow.com/questions/7709803/javascript-get-minutes-between-two-dates) – Heretic Monkey Sep 16 '20 at 13:47
  • @NikNik I am able to get the time difference between two date , but I haven't worked out how to have add them together to get the total time duration. Please have a look at my array and expected output – Jereme Sep 16 '20 at 13:52
  • That's clear but can you show the code that you tried and that didn't work for you? Maybe you just need to group the single results by name and then it's done. – NikNik Sep 16 '20 at 14:06

5 Answers5

1
let sleepResult = 0;
let awakeResult = 0;
array.forEach(item => {
  const diff = item.endTime - item.startTime
  if (item.name === 'sleep')
    sleepResult += diff
  if (item.name === 'awake')
    awakeResult += diff
})
console.log(`total duration sleep : ${sleepResult}`)
console.log(`total duration awake : ${awakeResult}`)

This will allow you to achieve what you asked.

Assuming you will format final log as

1 min 13 secs

Since sleepResult and awakeResult are timestamps

Mze
  • 197
  • 9
1

This is working for me:

let res = [
  {id: 1, name: "sleep", endTime: 1600261550535, startTime: 1600261541729}, // 9 sec
  {id: 2, name: "sleep", endTime: 1600261527833, startTime: 1600261522709}, // 5 sec 
  {id: 3, name: "sleep", endTime: 1600261496881, startTime: 1600261437616}, // 59 sec 
  {id: 4, name: "awake", endTime: 1600261427129, startTime: 1600261413596}, // 14 sec 
  {id: 5, name: "awake", endTime: 1600261403114, startTime: 1600261347569}, // 56 sec 
  {id: 6, name: "awake", endTime: 1600261337893, startTime: 1600261206497}, // 2 min 11 sec 
];
// accumulate the differences in milliseconds
res = res.reduce((a, e) => {
  a[e.name] = (a[e.name] || 0) + Math.abs(e.endTime - e.startTime);
  return a;
}, {})

// print the output extracting minutes and seconds
Object.entries(res).map(([k, v]) => {
  let minutes = Math.floor(v / 60000);
  let seconds = Math.floor((v - minutes * 60000) / 1000)
  console.log(`${k} : ${minutes} minutes and ${seconds}`)
})
Alberto Sinigaglia
  • 12,097
  • 2
  • 20
  • 48
1

You can accumulate the object based on the name into a Map using reduce. Once you have performed the accumulation/summation you can use Array.from on your Map with a mapping function to convert the values of your map into the desired format you're after. You can then forEach/loop over the entries of the map and print out the keys/values:

const arr = [ {id: 1, name: "sleep", endTime: 1600261550535, startTime: 1600261541729}, {id: 2, name: "sleep", endTime: 1600261527833, startTime: 1600261522709}, {id: 3, name: "sleep", endTime: 1600261496881, startTime: 1600261437616}, {id: 4, name: "awake", endTime: 1600261427129, startTime: 1600261413596}, {id: 5, name: "awake", endTime: 1600261403114, startTime: 1600261347569}, {id: 6, name: "awake", endTime: 1600261337893, startTime: 1600261206497}];

const ppTime = s => {
  const hours = Math.floor(s / 3600);
  const min = Math.floor(s / 60) % 60
  const secs = s % 60;
  return [[hours, 'hours'], [min, 'min'], [secs, 'secs']].filter(([f]) => f).map(arr => arr.join(' ')).join(' ');
}

const res = Array.from(arr.reduce((m, {name, endTime, startTime}) => {
  return m.set(name, (m.get(name) || 0) + (endTime - startTime));
}, new Map), ([k, v]) => [k, ppTime(Math.round(v/1000))]);

res.forEach(([name, time]) => {
  console.log(`total duration ${name} : ${time}`);
});
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
1

try this:

var timeStamps = [
 {id: 1, name: "sleep", endTime: 1600261550535, startTime: 1600261541729}, // 9 sec
 {id: 2, name: "sleep", endTime: 1600261527833, startTime: 1600261522709}, // 5 sec 
 {id: 3, name: "sleep", endTime: 1600261496881, startTime: 1600261437616}, // 59 sec 
 {id: 4, name: "awake", endTime: 1600261427129, startTime: 1600261413596}, // 14 sec 
 {id: 5, name: "awake", endTime: 1600261403114, startTime: 1600261347569}, // 56 sec 
 {id: 6, name: "awake", endTime: 1600261337893, startTime: 1600261206497}, // 2 min 11 sec 
];
var sleep = 0;
var awake = 0;
timeStamps.forEach((element) => {
    if(element.name == "sleep") {
        sleep = sleep + element.endTime-element.startTime;}
    if(element.name == "awake") {
        awake = awake + element.endTime-element.startTime;}});
var date = new Date(sleep);
var date1 = new Date(awake);
var sleepMinutes = date.getMinutes();
var sleepSeconds = date.getSeconds();
var awakeMinutes = date1.getMinutes();
var awakeSeconds = date1.getSeconds();

console.log("total amount of sleep: %s min %s sec",sleepMinutes, sleepSeconds);
console.log("total amount of awake: %s min %s sec",awakeMinutes, awakeSeconds);
Nbody
  • 1,168
  • 7
  • 33
1

This was a fun code challenge. I hope it helps you get to your final goal.

const getSleepAndDuration = (array) => {
    const finalTimesInSeconds = array.reduce(
        (accum, current) => {
            const start = moment(current.startTime);
            const end = moment(current.endTime);

            const diffInSeconds = end.diff(start, "seconds");
            accum[current.name] += diffInSeconds;
            return accum;
        },
        {
            sleep: 0,
            awake: 0,
        }
    );

    const { sleep, awake } = finalTimesInSeconds;
    const sleepText = getDurationText(sleep);
    const awakeText = getDurationText(awake);
    console.log(`total duration sleep: ${sleepText}`);
    console.log(`total duration awake: ${awakeText}`);
};


const getDurationText = (duration) => {
    const days = Math.floor(duration / 86400);
    const hours = Math.floor((duration - days * 86400) / 3600);
    const minutes = Math.floor((duration - days * 86400 - hours * 3600) / 60);
    const seconds = Math.floor(
        duration - days * 86400 - hours * 3600 - minutes * 60
    );

    let time = "";
    if (days) {
        time += `${days} ${days === 1 ? "day" : "days"}`;
    }
    if (hours) {
        time += ` ${hours} ${hours === 1 ? "hour" : "hours"}`;
    }
    if (minutes) {
        time += ` ${minutes} ${minutes === 1 ? "minute" : "minutes"}`;
    }
    if (seconds) {
        time += ` ${seconds} ${seconds === 1 ? "second" : "seconds"}`;
    }
    return time;
};