sooprise
sooprise

Reputation: 23187

Building a query that is most efficiently finds If a range of dates is in an interval?

Overlap exists between DateRange1 and DateRange2

DateRange1:        |-----------|
DateRange2:                |-------|

Overlap does not exist between DateRange3 and DateRange4

DateRange3:    |------|
DateRange4:                 |-------|

I have a query that checks if there is an overlap, but it's a little hairy. It involves checking each DateRange border and uses a lot of <'s and >'s.

I was wondering if you could say like, if DateRange1.Union(DateRange2) != null, do stuff. Just something to make my code more readable and less hairy.

Thanks!

Upvotes: 2

Views: 133

Answers (2)

digEmAll
digEmAll

Reputation: 57210

I'd create an extension method:

public static bool OverlappedTo(this DateRange range1, DateRange range2)
{
    return range1.OverlappedTo(range2.Start, range2.End);
}

// Just an example, implement as you prefer...
public bool OverlappedTo(this DateRange range1, DateRange range2)
{
    var duration1 = range1.End - range1.Start;
    var duration2 = range2.End - range2.Start;

    var minStart = range1.Start < range2.Start ? range1.Start : range2.Start;
    var maxEnd = range1.End > range2.End ? range1.End : range2.End;

    var totalDuration = maxEnd - minStart;

    // if the sum of the 2 durations is less than 
    // the total duration --> overlapped
    return duration1 + duration2 < totalDuration;
}

Usage:

bool overlapped = range1.OverlappedTo(range2);

P.S.

My DateRange class resemble to this:
(perhaps you have another implementation)

public class DateRange
{
    public DateTime Start { get; private set; }
    public DateTime End { get; private set; }

    public DateRange(DateTime start, DateTime end)
    {
        this.Start = start;
        this.End = end;
    }
}

EDIT:
(according to the comments)

var outSideRange = new DateRange(start, end);

var filteredRows = 
dt.AsEnumerable()
  .Where(x => outSideRange.OverlappedTo(x.Field<DateTime>("StartCol"),
                                        x.Field<DateTime>("EndCol")));

Upvotes: 1

Austin Salonen
Austin Salonen

Reputation: 50215

If you can add a IncludedDates property (IEnumerable<DateTime>), it should be pretty easy.

DateRange1.IncludedDates.Intersect(DateRange2.IncludedDates).Any()

Upvotes: 1

Related Questions