How to merge lists of overlapping date ranges

Look at that title... Now that's a problem that gave me quite some grief for too many hours: the algorithm to efficiently merge prioritized lists of overlapping date ranges.

First, I thought I had it in a minute, but then I saw it was wrong. After quite some fruitless tweaking of my initial solution, I started Googling for solutions but unfortunately I came across long forum threads of people guessing the solution (what a terrible waste of time that was). Then I started harassing everybody around me and together, after a few drawings of the problem on a piece of paper the solution lay before us (kudos to Jovan). After that, I typed the code with 2 fingers in the nose (figuratively speaking ;-) ).

To illustrate what I mean, just check out this proof-of-concept of a scheduling tool: you can schedule recurring tasks hierarchically in a list (drag 'n drop items to change priority) and the occurrences of the tasks are drawn out into a timeline. Plus, you can switch the view between an interval of a day or a week. It's actually directly based on the principle of a Gantt-chart and it's not a coincidence that I chose this type of representation because you can make this quite easily by extending a List component in Flex.

The problem stated in the title of this post needed to be solved in order to determine the action plan of this schedule: if we can do only one thing at a time (single thread) and we encounter overlapping task occurrences we need to decide which one to choose based on the priority level of the task. The "action plan" is indicated in that bright yellow that hurts in your eyes (seeing it? ;-) ).

Let's come to the point. First we need to break apart all starts and ends to individual points on the timeline. We do this by looping through all the occurrences for every task. With a task occurrence, I mean the date range or span between the start of an execution and its end. All these points in time, we need to store individually into value objects keeping together the date, the type of the point (start/end) and a reference to the task object in question. Do not forget to sort this list by date!
Secondly, generate all possible spans starting from the list we just created while ignoring to which task they belong. Important: include the start and end of the current interval view.
As a final step, we need to define to which task each of the newly created timespans belong. Loop through the list of spans, calculate the middle of each span and loop through each occurrence of every task to find the task with the highest priority in which that middle lies (tip: loop your list of tasks from the highest priority to the lowest and break the nested for loop by setting the indexes of both for loops to its maximum value as soon as you've found the task to attribute your merged date range to). And that's all there is to it.

If you want to build a scheduler with repeating tasks (ex. every day, every week, every month, on weekdays or weekends, etc.), then I suggest you check out this post about Cron4AS which served as the very basis for the scheduler PoC.

Concerning building schedulers, if you don't like the Gantt-alike approach, check out this tutorial on how to build an event calendar component: http://www.thetechlabs.com/tutorials/interfaces/create-a-dynamic-event-calendar-in-flex-builder-3-with-actionscript-30/.

This entry was posted in components, scheduling, tips, tools. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*