8

I have a nullable Date property called BoughtDate. I am trying the following:

if( item.BoughtDate.Value.Equals( DateTime.MaxValue) ) item.BoughtDate= null;

also tried this:

if( item.BoughtDate.Equals( DateTime.MaxValue) ) item.BoughtDate=null;

When debugging, my BoughtDate and DateTime.MaxValue seems exactly the same - yet it says it is not the same(does not set my item.BoughtDate to null)

Why does my comparison not work?

Jehof
  • 34,674
  • 10
  • 123
  • 155
user1702369
  • 1,089
  • 2
  • 13
  • 31
  • Do you need to cast it to a nullable datetime? `item.BoughtDate=(DateTime?)null;` – Niklas Jun 02 '17 at 08:56
  • 2
    Does the `BoughtDate` come from a database? Differences in the accuracy used to record dates can cause them to superficially appear the same, but differ by a small number of milliseconds (3, usually). – Paul Suart Jun 02 '17 at 08:57
  • `bool result = Nullable.Compare(DateTime.Now, yourDate) > 0;` – kashi_rock Jun 02 '17 at 08:58
  • Strange! This works well for me and my console statement gets printed `DateTime? BoughtDate = DateTime.MaxValue; if (BoughtDate.Value.Equals(DateTime.MaxValue)) { Console.WriteLine("equals comparison succeeded"); }` – RBT Jun 02 '17 at 09:00
  • Can you post a snapshot of your visual studio debugger when you are viewing the value present in `item.BoughtDate` in quick watch window? – RBT Jun 02 '17 at 09:02
  • 2
    The values are probably not the same. Check the Ticks-property of the DateTimes to verify if this is the case. – Andreas Zita Jun 02 '17 at 09:02

4 Answers4

9

The problem,as @PaulSuart points in the comments, is probably the milliseconds precision. DateTime.MaxValue.TimeOfDay is {23:59:59.9999999},but your BoughtDate.TimeOfDay is probably {23:59:59.9990000},so they are not equal.

What i would do is just comparing the dates, i think that's enough in most cases:

if( item.BoughtDate.Value.Date.Equals( DateTime.MaxValue.Date) ) item.BoughtDate= null;
Pikoh
  • 7,582
  • 28
  • 53
  • Better do add an extension similar to the one this answer suggests: https://stackoverflow.com/a/1005222/68432 - your code is ugly! – Paul Suart Jun 02 '17 at 09:14
  • @PaulSuart What do you find "ugly" in comparing the `Date` property of 2 `DateTime` ? – Pikoh Jun 02 '17 at 09:31
  • sorry, I was rude. I just meant that the intent in your code could be expressed more clearly by using an extension method. – Paul Suart Jun 02 '17 at 13:36
0

EDIT: As someone pointed out it doesn't answer the original question, just provides an alternative.

Try using DateTime.Compare

https://msdn.microsoft.com/pl-pl/library/system.datetime.compare(v=vs.110).aspx

public static void Main()
{
  DateTime date1 = new DateTime(2009, 8, 1, 0, 0, 0);
  DateTime date2 = new DateTime(2009, 8, 1, 12, 0, 0);
  int result = DateTime.Compare(date1, date2);
  string relationship;

  if (result < 0)
     relationship = "is earlier than";
  else if (result == 0)
     relationship = "is the same time as";         
  else
     relationship = "is later than";

  Console.WriteLine("{0} {1} {2}", date1, relationship, date2);
}

in your example maybe like that:

if(DateTime.Compare(item.BoughtDate.Value,DateTime.MaxValue) == 0) item.BoughtDate=null;
phoenix
  • 365
  • 1
  • 4
  • 15
  • This is a good alternative way to compare datetime values but OP is asking that why the `equals` API is returning wrong result for `DateTime?` (nullable datetime) type. – RBT Jun 02 '17 at 09:03
0

I did a quick test for your case:

static void Main(string[] args)
{
    DateTime? BoughtDate = DateTime.MaxValue;
    //subtract 100 milliseconds from it
    BoughtDate = BoughtDate.Value.AddMilliseconds(-1);

    Console.WriteLine(BoughtDate.Value.Hour); //23
    Console.WriteLine(DateTime.MaxValue.Hour); //23

    Console.WriteLine(BoughtDate.Value.Minute); //59
    Console.WriteLine(DateTime.MaxValue.Minute); //59

    Console.WriteLine(BoughtDate.Value.Second); //59
    Console.WriteLine(DateTime.MaxValue.Second); //59

    Console.WriteLine(BoughtDate.Value.Year); //9999
    Console.WriteLine(DateTime.MaxValue.Year); //9999

    Console.WriteLine(BoughtDate.Value.Month); //12
    Console.WriteLine(DateTime.MaxValue.Month); //12

    Console.WriteLine(BoughtDate.Value.Day); //31
    Console.WriteLine(DateTime.MaxValue.Day); //31

    Console.WriteLine(BoughtDate.Value.Millisecond); //998
    Console.WriteLine(DateTime.MaxValue.Millisecond); //999



    if (BoughtDate.Value.Equals(DateTime.MaxValue)) 
    {
        Console.WriteLine("equals comparison succeeded"); //doesn't get printed
    }
}

After reducing just one millisecond from original value it doesn't passes the equality check condition in if block but if you see the value of BoughtDate in quick watch window they seem exactly the same as you said (as it shows only year, month, day, hour, minute and second parts).

enter image description here

It shows millisecond part only when you expand the + sign.

So your date time variables must be differing in millisecond part even if they appear to be the same at one glance.

RBT
  • 24,161
  • 21
  • 159
  • 240
0

I think you might find answer in the below link if the Date you are fetching from SQL-Server. SQL-Server only supports the time range till 23:59:59.997 and this might cause few ticks less than what C# supports. You can just compare the dates as @Pikoh already mentioned.

https://learn.microsoft.com/en-us/sql/t-sql/data-types/datetime-transact-sql

Necromancer
  • 194
  • 3
  • 13