Jereme
Jereme

Reputation: 525

How to work out total duration between 2 timestamp? Javascript

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.

Upvotes: 0

Views: 116

Answers (5)

damianhouse
damianhouse

Reputation: 21

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;
};

Upvotes: 1

Nick Parsons
Nick Parsons

Reputation: 50759

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}`);
});

Upvotes: 1

Noa
Noa

Reputation: 1216

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);

Upvotes: 1

Alberto
Alberto

Reputation: 12939

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}`)
})

Upvotes: 1

Mze
Mze

Reputation: 187

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

Upvotes: 1

Related Questions