Reputation: 579
In my C# program I have run into an obstacle where I have a table that stores date ranges (columns are date range ID (int), begin date (DateTime) and end date (DateTime). I want to query the table and get back rows that only fall within a specific date range. I cannot use datetime.date since that includes the year.
So for example, I want to query the table and get all date ranges that fall between 01-01 and 5-31.
I have tried using the following lambda to query the table, but my result set is empty.
List<DateRanges> tempDateRangeList = dataContext
.DateRanges
.Where(r=>r.BeginDate.Month <= startDate.Month
&& r.EndDate.Month >= finishDate.Month)
.ToList();
tempDateRangeList = tempDateRangeList.Where(r=>r.BeginDate.Day <= startDate.Day
&& r.EndDate.Day >= finishDate.Day)
.ToList();
Does anyone have any suggestions on how I could accomplish this?
Edit:
Examples of BeginDate and EndDate would be a list such as follows:
BeginDate 1/1/2016, 5/25/2016, 9/11/2016
EndDates 5/24/2016, 9/10/2016, 12/31/2016
Filter date would be: startDate = 12/8 finishDate = 12/12
Expected result: Begin Date of 9/11 End date of 12/31
Upvotes: 9
Views: 9604
Reputation: 125
If a lambda expression isn't compulsory, I've used linq queries (because it was the first solution i've thought).
var validRanges = from range in ranges
where range.BeginDate.CompareTo(startDate) <= 0
where range.EndDate.CompareTo(endDate) >= 0
select range;
Using CompareTo is the easiest way to compare two DateTime struct. I invite you to take a look here for a complete description of the method.
If you aren't interested in hours of your dates, but only in Day and Month, you should use range.BeginDate.Date.CompareTo(startDate.Date)
and range.EndDate.Date.CompareTo(endDate.Date)
Upvotes: 0
Reputation: 11321
There are two cases in your condition - month equal to boundary month, in which case you must test day number, and a different month, in which you ignore day. Hence the query:
List<DateRanges> tempDateRangeList =
dataContext.DateRanges.Where(r =>
((r.BeginDate.Month < startDate.Month) ||
(r.BeginDate.Month == startDate.Month && r.BeginDate.Day <= startDate.Day)) &&
((r.EndDate.Month > finishDate.Month) ||
(r.EndDate.Month == finishDate.Month) && r.EndDate.Day >= finsihDate.Day))
.ToList();
Condition is ugly and very hard to follow but covers all cases. This query returns all records which define date ranges that completely fall under the boundary dates.
If you wish to find records that are just overlapping (completely or partially) with the filtering range, then the query would be:
List<DateRanges> tempDateRangeList =
dataContext.DateRanges.Where(r =>
((r.BeginDate.Month < endDate.Month) ||
(r.BeginDate.Month == endDate.Month && r.BeginDate.Day <= endDate.Day)) &&
((r.EndDate.Month > startDate.Month) ||
(r.EndDate.Month == startDate.Month) && r.EndDate.Day >= startDate.Day))
.ToList();
This condition may bend your mind, but it works fine.
Upvotes: 3