Comparing nullable DateTime?

51,560

Solution 1

Your question is not quite clear to me, but if we have

DateTime? ExpireDateTime;  // could be a variable or a property

it's OK to say just

if (ExpireDateTime < DateTime.UtcNow)
{
  ...
}

This will be OK if ExpireDateTime is null (HasValue is false). Some inexperienced developers will struggle to understand lifted operators, so to make it more clear, you could write

if (ExpireDateTime < (DateTime?)DateTime.UtcNow)
{
  ...
}

It's the same, but easier to read and understand.

Never write .Value if the nullable might be null, of course. You will get an InvalidOperationException "Nullable object must have a value" if you do so.

Solution 2

I would recommend you to use the following:

int y = Nullable.Compare<DateTime>(DateTime.UtcNow, x); 

// x is the nullable date time object.
// y will be '-1' if x is greater than DateTime.UtcNow

Solution 3

The compiler lifts variables and generates code to check for nulls.

> new DateTime?()
null
> DateTime.Now > null
false
> DateTime.Now < null
false

> new int?()
null
> 10 >= null
false
> 10 =< null
false
> 10 == null
false
> 10 != null
true

Knowing this you can write simple code.

// d is a DateTime? 
DateTime now = DateTime.Now;

bool after = d > now;
bool before = d < now;
bool today = d?.Date == now.Date;

If d is null everything will be false, else it will work like normal DateTime comparison.

Solution 4

If ExpireDateTime is a Nullable<DateTime>i would do following instead:

if (ExpireDateTime.HasValue && ExpireDateTime < DateTime.Now.ToUniversalTime())
{ 
}

Solution 5

Use the Value property of the nullable:

objet.ExpireDateTime.Value

if (!object.ExpireDateTime.IsNull() 
    && DateTime.Compare(objet.ExpireDateTime.Value, 
                        DateTime.Now.ToUniversalTime()) < 0)
{ 
}    
Share:
51,560
genxgeek
Author by

genxgeek

20+ years of full-stack development and technical project management delivering global software solutions across manufacturing, consumer products and business analytics.

Updated on July 09, 2022

Comments

  • genxgeek
    genxgeek almost 2 years

    Looking for a better way to compare a nullable date time than the following:

    Any suggestions?

    // myobject.ExpireDatetime is of DateTime?
    //
    if (!myobject.ExpireDateTime.IsNull() && DateTime.Compare((DateTime)myobject.ExpireDateTime, DateTime.Now.ToUniversalTime()) < 0)
    { //error! }    
    

    Edited: Sorry for confusion...myobject.ExpireDatetime is of type DateTime.

  • Jeppe Stig Nielsen
    Jeppe Stig Nielsen over 11 years
    There's still a smell left from the Original Question as (in the usual implementation) System.Object does not have a static member called ExpireDateTime (so it still won't compile).
  • Oded
    Oded over 11 years
    @JeppeStigNielsen - ExpireDateTime is probably an extension method.
  • Jeppe Stig Nielsen
    Jeppe Stig Nielsen over 11 years
    @Oded You can't extend like that. Even with an extension method you need an identifyer or an ordinary exression before the dot (.). For example (new object()).ExpireDateTime() or typeof(object).ExpireDateTime() or @object.ExpireDateTime() all might compile with some (really crazy) extension method. But there's something wrong with just object. Besides, if it's a method, you can't just say .IsNull without first invoking ExpireDateTime. In short, it can never ever be valid as it stands.
  • genxgeek
    genxgeek over 11 years
    Sorry for the confusion...object.ExpireDateTime is of type DateTime.
  • genxgeek
    genxgeek over 11 years
    Awesome! Yes, this is the explanation that I was really after. That is, how to compare a nullable datetime without short circuiting logic in by checking if the value is not null...then checking the constraint on the nullable value <psuedo code> if (val.isnotnull && val.iswithinconstraint)
  • Jeppe Stig Nielsen
    Jeppe Stig Nielsen over 11 years
    @JaJ It's not legal to write object "dot" ExpireDateTime in the code.
  • labroo
    labroo over 8 years
    but, (default(DateTime?) < DateTime.UtcNow) is false and ( default(DateTime?) > DateTime.UtcNow) is also false
  • Jeppe Stig Nielsen
    Jeppe Stig Nielsen over 8 years
    @labroo Certainly. So with nullables we do not have "trichotomy", so sometimes x < y and x == y and x > y are all false.
  • JustAMartin
    JustAMartin about 8 years
    It also depends on specific business requirements. In some occasions I might want to treat null date as "greater than" any valid date. For example: minDate = d1 < d2 ? d1 : d2 where all three dates are nullable - in this case I want minDate to receive actual valid date, if any, but not null, unless both d1 and d2 are nulls.
  • Jeppe Stig Nielsen
    Jeppe Stig Nielsen over 5 years
    @JustAMartin If you really want, you can write !(ExpireDateTime >= DateTime.UtcNow) which is the same as ExpireDateTime < DateTime.UtcNow if null is not involved, but has the opposite value when null is involved. However, it may be easier to read something like !ExpireDateTime.HasValue || ExpireDateTime.Value < DateTime.UtcNow, depending on taste.