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
- SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.
- Yup Date Format Validation With Moment JS
- Yup Number Validation: Allow Empty String
- Exactly Same Query Behaving Differently in Mongo Client and Mongoose
- JavaScript Unit Testing JSON Schema Validation
- Reduce JS Size With Constant Strings
- JavaScript SDK