Skip to content

Instantly share code, notes, and snippets.

@gdibble
Created October 4, 2019 22:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gdibble/21b4f9147b496555f07ff4fafb078a59 to your computer and use it in GitHub Desktop.
Save gdibble/21b4f9147b496555f07ff4fafb078a59 to your computer and use it in GitHub Desktop.
findDateRanges: Find and group date-ranges in an Array of dates
/**
* @function findDateRanges
* @description Find and group date-ranges in an Array of dates
*
* @param {Array} sourceCollection - containing ISODateStrings in any order
* @param {?Array} destinationCollection - defaults to []
*
* @returns {Array} - ^destinationCollection passed or new Array
*
* @example findDateRanges([
* '2001-01-07T07:07:07.070Z',
* '2001-01-04T04:04:04.040Z',
* '2001-01-04T04:02:04.016Z',
* '2001-01-02T02:02:02.020Z',
* '2001-01-01T01:01:01.010Z'
* ]) --> [ // As Date Objects:
* [ 1/1/2001, 1/2/2001 ],
* [ 1/4/2001, 1/4/2001 ],
* [ 1/7/2001 ] }
* ]
*/
const findDateRanges = (sourceCollection, destinationCollection=[]) => {
const toDate = dateString => new Date(dateString);
const datesObjsSortedAsc = [].concat(sourceCollection).map(toDate).sort((a, b) => a === b ? 0 : a > b ? 1 : -1);
for (let i = 0, l = datesObjsSortedAsc.length, a, d, p, pd; i < l; i++) {
a = function addToRange() {
p = [];
p.push(d);
destinationCollection.push(p);
};
d = toDate(datesObjsSortedAsc[i]); // Date as Date Object
if (p) { // Has p (previous-range)
pd = p[p.length - 1]; // Previous-date
// Determine if date is part of range
if (
d.getUTCFullYear() === pd.getUTCFullYear() && // Same year
d.getUTCMonth() === pd.getUTCMonth() && // Same month
([ 0, -1 ].indexOf(pd.getUTCDate() - d.getUTCDate()) > -1) // 0-1 day later (duplicate date handling)
) {
// Part of range
p.push(d);
} else {
// New range
a();
}
} else {
// Initial loop iteration
a();
}
}
return destinationCollection;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment