title: Bug in Timeline Gap-Detection Algorithm
body: <p>I have an algorithm that examines an array of <code>Event (StartTime,EndTime)</code> on a timeline that runs from Midnight->Midnight to check for any gaps. The algorithm works, but there is one configuration where it doesn't work.</p>
  
  <p>Before I show the code, here's the specific case where it doesn't work: When I have a Midnight-ending Event with the same <code>StartTime</code> as another event which does not end at midnight. The problem here is that I add an erroneous GAP to my result, a <code>GAP (Midnight,Midnight)</code>. <strong>It shouldn't be there in my result.</strong></p>
  
  <p><a href="https://i.stack.imgur.com/BECdm.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/BECdm.jpg" alt="enter image description here"></a></p>
  
  <p>Now the code: All Events (including GAP Events) have a <code>(StartTime,EndTime)</code>. I am receiving an incoming array of normal <code>proposedEvents</code>, and my job is to return a filled-out array of <code>preparedGapEvents</code>.</p>
  
  <pre><code>function schedulerPrepareGapEvents(proposedEvents) {
  
  var preparedGapEvents = [];
  
  // First sort proposed events by StartTime
  proposedEvents.sort(sortObjectsByStartTime); // sort by StartTime of the event
  
  // If there are no proposed events, exit immediately with an empty result
  if (proposedEvents.length == 0) {
      return preparedGapEvents;
  }   
  
  // Manually add first gap, if it exists: Sorted Proposed Event #1 not starting at 12:00am
  var startTimeFirst = getTimestampFromString(proposedEvents[0].startTime);
  if (startTimeFirst &gt; 0) {
      preparedGapEvents.push({"gapEventID" : "event-GAP" + generateUniqueID(), 
                              "gapEventColor" : globalGapEventColor, 
                              "gapEventStartTimestamp" : 0, 
                              "gapEventEndTimestamp" : startTimeFirst});      
  }
  
  // Initially lastMaxEndTime is the End Time of 1st Event
  var lastMaxEndTime = getTimestampFromString(proposedEvents[0].endTime); 
  
  // Main Event Traversal Loop
  jQuery.each(proposedEvents, function(index, item) {     
  
      // Get the current proposed event's StartTime/EndTime in the loop
      var startTimeCurrent = getTimestampFromString(item.startTime);
      var endTimeCurrent = getTimestampFromString(item.endTime);
  
      // Next neighboring proposed event
      var nextEvent = proposedEvents[index+1];
  
      // If Next Proposed Event exists
      if (nextEvent != null) {
          var startTimeNext = getTimestampFromString(nextEvent.startTime);
          var endTimeNext = getTimestampFromString(nextEvent.endTime);
  
          if (startTimeNext &gt; lastMaxEndTime) { // Gap detected! 
              preparedGapEvents.push({"gapEventID" : "event-GAP" + generateUniqueID(), 
                                      "gapEventColor" : globalGapEventColor,
                                      "gapEventStartTimestamp" : lastMaxEndTime, 
                                      "gapEventEndTimestamp" : startTimeNext});               
          }
  
          // Keep track of the current MAX EndTime: either this new event's EndTime or the previous Max EndTime
          lastMaxEndTime = Math.max(lastMaxEndTime, endTimeNext);
      }
      else {
          // Last Proposed Event (no next neighbor): its End Time must be at the 24-hr END mark, otherwise a gap
          if (endTimeCurrent &lt; 1440) {
              preparedGapEvents.push({"gapEventID" : "event-GAP" + generateUniqueID(), 
                                      "gapEventColor" : globalGapEventColor,
                                      "gapEventStartTimestamp" : lastMaxEndTime, 
                                      "gapEventEndTimestamp" : 1440});
          }
      }
  }); 
  
  return preparedGapEvents;
  </code></pre>
  
  <p>The problem here is somewhere in the main loop. After I sort by <code>StartTime</code>, the two adjoining events can be either in Position 0 or 1, <strong>depending on chance</strong>. Suppose that by chance I have a neighbor in the +1 position that I will examine. In that case, I fall into the ELSE, and satisfy the condition <code>if (endTimeCurrent &lt; 1440)</code> because that event's End Time is not 1440 (Midnight)!</p>
  
  <p>So how do I fix this?</p>