Had an interesting problem a few nights ago which at first seemed like a really easy thing, but turned out to be a right pain in the face. I figured I’d do a blog on it as it might help someone else later on.
A Simple Problem .. not !!
What I wanted to figure out was if two date ranges overlapped. the logic of this was a lot harder to get my head around than I first expected. As I was dealing with a range rather than static dates any of the existing DateTime functions were useless, also working with TimeSpans I find difficult. The solution was to create a good Test case and keep playing around with the logic.
[Test(Description="Test over lapping dates")]
[TestCase("2009-12-17 13:00:00", "2009-12-17 17:00:00", "2009-12-17 13:00:00", "2009-12-17 13:00:00", true)]
[TestCase("2009-12-17 13:00:00", "2009-12-17 13:30:00", "2009-12-17 14:00:00", "2009-12-17 14:30:00", false)]
public void CompareDatesTest(string firstStartDate, string firstEndDate, string secondStartDate, string secondEndDate, bool expectedOverlap)
{
DateTime first_start_date = DateTime.Parse(firstStartDate);
DateTime first_end_date = DateTime.Parse(firstEndDate);
DateTime second_start_date = DateTime.Parse(secondStartDate);
DateTime second_end_date = DateTime.Parse(secondEndDate);
//Compare
Assert.IsTrue(DatesOverlap(first_start_date, first_end_date, second_start_date, second_end_date) == expectedOverlap, "booking overlap validation did not work");
}
the test case above will run two dates through my logic and return True if the first and second date rages overlap, False if they don’t.
My magic function
To work out the problem I had to convert the dates into Ticks. This converts the date in the number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001. Using that conversion I can easily use the numerical Great-than Boolean functions…. so after much playing around with IF statements I came up with:
private bool DatesOverlap(DateTime firstStart, DateTime firstEnd, DateTime secondStart, DateTime secondEnd)
{
return (firstEnd.Ticks >= secondStart.Ticks) && (secondEnd.Ticks >= firstStart.Ticks);
}
After doing all this I then did a quick Google to find someone had come up with the same solution. D’oh!.