Задача напоминает построение гистограммы. Весь интервал бьётся на отрезки по 15 минут, и считается, сколько событий «упадёт» в каждое из ведёрок.
Я бы сделал так. На вход функции передаются данные отсчётов, время начала и время конца.
Сначала подготовить ответ – объект, где ключи это время начала 15-минуток, а значения пока нули. Будут числа событий, попадающие в эти интервалы.
Перебирать каждое событие. Брать его время начала. Смотреть, попадает ли вообще в исследуемый диапазон. Высчитывать начало его 15-минутки, округлив деление времени до ближайшего начала 15-минутки в меньшую сторону. Прибавлять 1 нужному «ведёрку».
/**
* @param array hits - массив данных об ударах.
* @param int start - начало интервала (включён), число миллисекунд с 1 января 1970 UTC
* @param int finish - конец интервала (исключён), число миллисекунд с 1 января 1970 UTC
*
* @return возвращает объект, где ключи – моменты начала 15-минуток, а значения – число событий
*/
function bins( hits, start, finish) {
var i
,step = 15 * 60 * 1000 // 15 минут в миллисекундах
,bins = {}
;
// заполнить ячейки нулями
i = start;
do { bins[i] = 0 } while( i += step < finish);
// перебрать все сэмплы
for(i = 0; i < hits.length; i++) {
hitTime = hits[i].ts; // считаем, что значение времени лежит в свойстве "ts"
if( hitTime < start || hitTime >= finish) continue; // вне диапазона
binTime = start + Math.floor( (hitTime - start) / step) * step; // в какое ведёрко попадает
bins[ binTime]++;
}
return bins;
}