Не очень понимаю, чего вы с задачей про Excel делаете в этой теме, но свой велосипед тем не менее предложу. Допущения: а) данные о каждом звонке записаны в одну строчку в три колонки, б) данные упорядочены по времени начала звонка, в) обработка будет вестись унутре Excel'я посредством VBA (хотя последнее не очень важно, на самом-то деле).
(Смысл алгоритма такой -- по первой строчке берём начало текущего учитываемого промежутка; дальше смотрим, сколько ещё звонков начинаются в это же время; дальше ищем начало следующего промежутка -- это либо конец одного из звонков, либо начало какого-то из следующих звонков; уже учтённые данные стираются.)
Алгоритм детализировался методом "где левая пятка скажет, там и уточню", переменных для хранения состояния должно быть минимум 4 -- начальное время рассматриваемого промежутка (StartTime), конечное время рассматриваемого промежутка (EndTime), количество звонков за рассматриваемый промежуток (CurrentCount) и номер текущего ряда на листе "Результат" (CurrentResultRowIdx).
Инициализация переменной с номером текущего ряда (CurrentResultRowIdx) должна происходить до начала обработки, остальные три (хранящие состояние рассматриваемого промежутка) должны обнуляться в начале каждого прохода по циклу.
0. Копируем исходные данные "куда-нибудь", куда не очень жалко, потому что оне в процессе помрут; в этом "куда-нибудь" помимо листа с исходными данными должен быть лист с "результатом обработки" -- пусть это будут "Данные" и "Результат". Формат листа "Результат" -- два столбца на дату и время начала промежутка, два столбца на дату и время окончания промежутка, столбец с количеством звонков за этот промежуток.
1.
[На листе "Данные"] берём начальное время звонка (полное, вместе с датой; сохраняем в StartTime) из первой строчки. (Если оно там есть; если первая строчка пустая -- сворачиваемся.)
2.
[На листе "Данные"] Смотрим, сколько ещё звонков началось в это время (смотрим данные во втором столбце, пока либо они не кончатся, либо не сменится время, сохраняем это значение в CurrentCount).
3.
[На листе "Данные"] в текущих обрабатываемых звонках (число которых см. в CurrentCount) ищем наиболее раннее время завершения звонка (тоже полное, вместе с датой; сохраняем в EndTime). (EndTime обязательно надо сравнивать ещё и с началом "следующего" звонка -- который будет в ряду (CurrentCount+1), иначе из-за длинных звонков пропадёт много-много данных.)
4.
[На листе "Результат"] Записываем время начала промежутка, время окончания промежутка и количество звонков за промежуток. (А заодно увеличиваем на единицу CurrentResultRowIdx.)
5.
[На листе "Данные"] в текущих обрабатываемых звонках (число которых см. в CurrentCount) заменяем время начала звонка на EndTime.
6.
[На листе "Данные"] в текущих обрабатываемых звонках (число которых см. в CurrentCount) удаляем все строчки, в которых StartTime = EndTime.
7. См. п. 1.
Более чем уверен, что есть решения проще (и уж точно должны быть решения быстрее).
Ещё здесь не обрабатывается случай, когда звонок нулевой длины (времена начала звонка и конца звонка совпадают). Понятия не имею, как в вашей "бизнес-логике" это надо учитывать. Если учитывать не надо, то такие случаи отлавливаются в процессе определения CurrentCount (п. 2) и по мере обнаружения изничтожаются (в CurrentCount они учитываться, естественно, не должны).
При такой преобработке никто, кроме таких краевых случаев, вроде бы пострадать не должен.
В роли цикла выступает While.
Ещё на листе "Результат" логи будут скорее всего прерываться -- и перед практическим употреблением очень даже стоит пройтись по этому листу (снизу вверх -- потому что придётся добавлять строчки) и если у соседних рядов не совпадают начало промежутка нижнего ряда с концом промежутка верхнего ряда, добавлять строчку с недостающим промежутком, а в количество звонков за этот промежуток писать ноль.
Вроде всё.
Добавлено: В принципе, какой-то там лист "Результат" и не нужен вовсе -- можно же всё просто тупо append'ить в файл (т. е. минус одна переменная для хранения состояния)
Добавлено: Чуть не забыл учесть длинные звонки
Точно спать пора.