Aaron
Aaron

Reputation: 4480

Comparing dates when date my be null

I am trying to get all dates in a Linq query between StartDate and EndDate. Both my StartDate and EndDate are the right dates, but my results are inconsistent. Everything else in the query works, just not the comparison of the dates. What am I doing wrong?

where (startDate == null || DateTime.Compare((DateTime)startDate,
o.FirstAirDate) < 0) && (endDate == null|| DateTime.Compare(
o.FirstAirDate, (DateTime)endDate) > 0)

Dates are showing up outside of the range and when I move the dates closer together nothing appears. For example If I search from December 21-26 I get results between those two dates but also a date for the 27th shows up. If I search from December 23-26 nothing shows up, even though I saw dates in this range show up when I searched from December 21-26

Upvotes: 4

Views: 2909

Answers (2)

Jeppe Stig Nielsen
Jeppe Stig Nielsen

Reputation: 61952

Your last inequality:

DateTime.Compare(o.FirstAirDate, (DateTime)endDate) > 0

is the wrong way. Compared to the first inequality, which looks correct, you can either swap the two arguments to Compare, or change < 0 into > 0. But you do both, which cancels each other.

It is easier to simply use comparison between DateTime values directly, for example:

where (startDate == null || (DateTime)startDate < o.FirstAirDate)
  && (endDate == null || o.FirstAirDate < (DateTime)endDate)

May I ask, is the declared C# type (compile-time type) of startDate, and endDate, object or DateTime? (i.e. Nullable<DateTime>). If they are Nullable<>, if you dare, you can use negation and lifted operators and turn this into:

where !(o.FirstAirDate <= startDate) && !(endDate <= o.FirstAirDate)

Note that the null checks are included here. If an operand to <= is null, the result is false, and because of the negation it will work in the null cases because of that.

Upvotes: 2

Bardicer
Bardicer

Reputation: 1469

If you're trying to get all instances where FirstAirDate is between startDate and endDate (and either startDate or endDate can be null) and they are all DateTime objects you might want to try something like:

var objects = MyObjectsList.Where(o => 
     (!startDate.HasValue || o.FirstAirDate >= startDate.Value) 
  && (!endDate.HasValue || o.FirstAirDate <= endDate.Value))

You can compare dates with simple comparison operators, just have to use the .Value for the nullable DateTime properties when doing the comparison - in which case it's best to null check first.

Upvotes: 7

Related Questions