JavaScript Find Total Time Duration

Excluding overlapping and idle times

Say we have a an array of objects with start and end times in each. This could be anything, ranging from work experience (the way LinkedIn shows per job), to education, to sports career. We want to sum all these small experiences, excluding overlapping and idle times, and give out the total duration, which can further be converted into years, months, or days.

Here’s the coded example with comments to understand the algorithm.

const getTotalExperienceInYears = (experience) => {

  // convert start & end strings to dates.
  // then sort by start date
  const sortedExperience =
    experience.map(e => ({
      ...e,
      startDate: new Date(e.startDate),
      endDate: new Date(e.endDate)
    }))
      .sort((a, b) => a.startDate - b.startDate);


  // this array will only have non-overlapping experiences
  // and each end start date difference
  const uniqueExperience = [];

  sortedExperience.forEach(ex => {
    // push if first, or non-overlapping
    if (!uniqueExperience.length
      || ex.startDate > uniqueExperience[uniqueExperience.length - 1].endDate) {
      uniqueExperience.push({
        startDate: ex.startDate,
        endDate: ex.endDate,
        diff: ex.endDate - ex.startDate
      });
    } // else last unique experience's endDate becomes the start date of new entry
    else if (ex.startDate < uniqueExperience[uniqueExperience.length - 1].endDate) {
      uniqueExperience.push({
        startDate:
          uniqueExperience[uniqueExperience.length - 1].endDate,
        endDate: ex.endDate,
        diff:
          ex.endDate - uniqueExperience[uniqueExperience.length - 1].endDate
      })
    }
  });


  const sumOfExperience =
    uniqueExperience.reduce((partialSum, a) => partialSum + a.diff, 0);

  const sumOfExperienceInYears =
    sumOfExperience / (1000 * 60 * 60 * 24 * 365);

  const yearsRoundedOff =
    Math.round((sumOfExperienceInYears + Number.EPSILON) * 100) / 100;

  return yearsRoundedOff;
}

For the above algorithm the assumption is that each experience object will have valid start and end dates and the key names are startDate & endDate.

The code can be run with the following example data:

const workExperience = [
  {
    title: "Software Internee",
    organization: "ABC",
    startDate: "2010-02-02",
    endDate: "2010-08-11",
  },
  {
    title: "Software Internee",
    organization: "DEF",
    startDate: "2010-07-20",
    endDate: "2011-01-15",
  },
  {
    title: "Associate Software Engineer",
    organization: "A",
    startDate: "2011-04-10",
    endDate: "2013-06-25",
  },
  {
    title: "Associate Software Engineer",
    organization: "B",
    startDate: "2013-06-01",
    endDate: "2014-06-01",
  },
  {
    title: "Software Engineer",
    organization: "B",
    startDate: "2014-06-02",
    endDate: "2016-06-01",
  },
  {
    title: "Senior Software Engineer",
    organization: "B",
    startDate: "2016-06-02",
    endDate: "2016-12-31",
  },
  {
    title: "Backend Team Lead",
    organization: "C",
    startDate: "2017-02-01",
    endDate: "2019-12-31",
  },
  {
    title: "Engineering Manager",
    organization: "D",
    startDate: "2019-12-01",
    endDate: "2022-06-08"
  },
];



console.log(
  getTotalExperienceInYears(workExperience)
);

// => 12.03

The total number of experience in our particular example, excluding overlaps and idle times, is around 12 years.

We can also use some library to further humanize the total duration information, for example: “8 years, 2 months”.

See also