11

I am trying to compare two DateTime variables which are having the same values in it.

But when I use Equals method it returns false which indicates "Not Equal".

My code is :

DateTime date = DateTime.Parse("2/27/2010 1:06:49 PM");
foreach (KeyValuePair<DateTime, List<string>> k in Sample)
{
   if (date.Equals(k.Key))
   {
      Console.WriteLine("Yes");
   }
   else {
      Console.WriteLine("No");
   }
}

The dictionary Sample contains the following keys :

  • 5/8/2018 11:18:00 AM
  • 5/8/2018 11:17:46 AM
  • 2/27/2010 1:06:49 PM
  • 5/8/2018 11:18:08 AM

The third key value is same as the comparing value.

And for all the key I get no as output.

Can anyone explain why it is happening like this ?

stuartd
  • 70,509
  • 14
  • 132
  • 163
  • 2
    `DateTime` contains not only seconds but also milliseconds and ticks. Maybe they are not equal – Tim Schmelter May 09 '18 at 10:22
  • 2
    Are you sure it is *exactly* the same value? just because they *display* the same doesn't mean they are *exactly* the same - precision, etc – Marc Gravell May 09 '18 at 10:23
  • How is the collection being populated? Using DateTime.Now? Could you provide an example? – Danielle Summers May 09 '18 at 10:24
  • This is rather strange. I'd check if the members of the `date` are the same as it is in the list. There might be some changes in timezone, depending on the method of creation of the instances, There might also me some differences in milliseconds and so on. – Matyas May 09 '18 at 10:26
  • You should define the format for Datetime to match the ones in the dictionary – yazan May 09 '18 at 10:31
  • `Tick` are different in both `Sample.Keys` and `date` .try a exerciser what i have suggested in my answer, you will have better idea then. – Amit May 09 '18 at 10:44
  • @yazan: A `DateTime` value doesn't have a format. It's just a date/time. It has a `Kind`, but that's not examined in `Equals` anyway IIRC. I strongly suspect this is just a subsecond difference. – Jon Skeet May 09 '18 at 10:45

6 Answers6

16

As i've commented, DateTime contains not only seconds but also milliseconds and ticks. Maybe they are not equal. But you culd use following extension method to compare only up to the seconds:

public static class DateTimeExtensions
{
    public static bool EqualsUpToSeconds(this DateTime dt1, DateTime dt2)
    {
        return dt1.Year == dt2.Year && dt1.Month == dt2.Month && dt1.Day == dt2.Day &&
               dt1.Hour == dt2.Hour && dt1.Minute == dt2.Minute && dt1.Second == dt2.Second;
    }   
}

Sample:

DateTime date1 = DateTime.Parse("2/27/2010 1:06:49 PM", CultureInfo.InvariantCulture);
DateTime date2 = date1.AddMilliseconds(100);
bool equals = date1.EqualsUpToSeconds(date2); // true
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • 2
    Since `DateTime.Ticks` is in units of 1/10000000 sec, you could just compare like so: `return dt1.Ticks/10000000 == dt2.Ticks/10000000;` which would probably be more efficient. – Matthew Watson May 09 '18 at 10:35
7

DateTime.Equals (static or instance) will compare the Ticks property. While it may appear to you that both dates are same (due to the way it is displayed for human readability) they may or may not be same. Tick is rather high precision measurement (1 tick = 100 nanoseconds).

It the values in the KeyValuePair are coming from some system generated date time, it will have different value than you creating your own date time object with static values.

For instance, take a look at these two dates,

DateTime one = new DateTime(636614784317968133);
DateTime two = new DateTime(636614784317968134);

They have 100 nanosecond difference. In the add watch they both look same but Equals method will return false for both.

enter image description here

If you want to remove the values after say milliseconds, you can use the following code:

one = one.AddTicks(-one.Ticks % TimeSpan.TicksPerMillisecond);
two = two.AddTicks(-two.Ticks % TimeSpan.TicksPerMillisecond);

Once this is done, you can see that Ticks for both the date objects are same and can be compared now.

danish
  • 5,550
  • 2
  • 25
  • 28
1

Out of curiosity, just tested this and it works fine

public static void Main()
{
    Dictionary<DateTime, List<string>> Sample = new Dictionary<DateTime, List<string>>();
    Sample.Add( DateTime.Parse("5/8/2018 11:18:00 AM"), new List<string>());
    Sample.Add( DateTime.Parse("5/8/2018 11:17:46 AM"), new List<string>());
    Sample.Add( DateTime.Parse("2/27/2010 1:06:49 PM"), new List<string>());
    Sample.Add( DateTime.Parse("5/8/2018 11:18:08 AM"), new List<string>());    
    DateTime date = DateTime.Parse("2/27/2010 1:06:49 PM");
  foreach (KeyValuePair<DateTime, List<string>> k in Sample)
  {
    if (date.Equals(k.Key))
    {
       Console.WriteLine("Yes");
    }
    else {
       Console.WriteLine("No");
    }
   }
 }      

Output:

No

No

Yes

No

dotNetFiddle

EDIT:

As suggested by @Fabjan

Change one of your lines of code to: Sample.Add( DateTime.Parse("2/27/2010 1:06:49.123 PM"), new List<string>()); and try again

In such case of DateTime.Ticks:

if (date.Ticks/10000000 == k.Key.Ticks/10000000)
   {
      Console.WriteLine("Yes");
   }
   else {

      Console.WriteLine("No");
   }

dotNetFiddle

DirtyBit
  • 16,613
  • 4
  • 34
  • 55
  • in his case, Ticks of sample date list must be different. dates are same till seconds but not in ticks.. I had same situation see the [question](https://stackoverflow.com/questions/49167098/any-method-on-listdatetime-doesnt-work-as-per-expectation) – Amit May 09 '18 at 10:34
  • @Amit in such case, `if (date.Ticks.Equals(k.Key.Ticks)) { //`would do it. – DirtyBit May 09 '18 at 10:42
  • of course it will help him. (in fact i have added that in my answer too). but that is really interesting how one can get stuck in comparing two simple dates. Just because `Ticks` property of dates are not much common in use for all people. – Amit May 09 '18 at 10:48
  • 1
    Change one of your lines of code to: `Sample.Add( DateTime.Parse("2/27/2010 1:06:49.123 PM"), new List());` and try again – Fabjan May 09 '18 at 10:53
  • @Fabjan that is exactly what i was saying! – Amit May 09 '18 at 10:59
0

Could this be a cultural problem? Try specific the right CultureInfo for comparing.

static void Main(string[] args)
{
    var culture = new CultureInfo("en-US", false);
    Dictionary<DateTime, List<string>> Sample = new Dictionary<DateTime, List<string>>();

    Sample.Add( DateTime.Parse("5/8/2018 11:18:00 AM", culture), new List<string>());
    Sample.Add( DateTime.Parse("5/8/2018 11:17:46 AM", culture), new List<string>());
    Sample.Add( DateTime.Parse("2/27/2010 1:06:49 PM", culture), new List<string>());
    Sample.Add( DateTime.Parse("5/8/2018 11:18:08 AM", culture), new List<string>());

    DateTime date = DateTime.Parse("2/27/2010 1:06:49 PM", culture);
    foreach (KeyValuePair<DateTime, List<string>> k in Sample)
    {
        if (date.Equals(k.Key))
        {
            Console.WriteLine("Yes");
        }
        else
        {
            Console.WriteLine("No");
        }
    }
}
  • in his case, Ticks of sample date list must be different. dates are same till seconds but not in ticks.. I had same situation see the question – Amit May 09 '18 at 10:50
0

here in your question, you have shown that even if your dates in sample are same as the date you are matching but still they are not Equal as per Equal()

you should debug and trying comparing Ticks of both dates.

Try below code

DateTime date = DateTime.Parse("2/27/2010 1:06:49 PM");
foreach (KeyValuePair<DateTime, List<string>> k in Sample)
{
   //if both Ticks are same, you should expect dates to be equal
   Console.WriteLine(date.Ticks + "-" + k.Key.Ticks);
   if (date.Equals(k.Key))
   {
      Console.WriteLine("Yes");
   }
   else {
      Console.WriteLine("No");
   }
}

This way you will log Ticks while matching dates.

your actual way to compare two dates here should be

DateTime date = DateTime.Parse("2/27/2010 1:06:49 PM");
foreach (KeyValuePair<DateTime, List<string>> k in Sample)
{
   if (date.Ticks == k.Key.Ticks)
   {
      Console.WriteLine("Yes");
   }
   else {
      Console.WriteLine("No");
   }
}

Comment here if it doesn't solve your concern.

Amit
  • 1,821
  • 1
  • 17
  • 30
0

Equals for structure (DateTime) i.e. value type check values are equal or not , but for date time DateTime.Compare is already there , you can use it

if (DateTime.Compare(date.Equals,k.Key) == 0)
   {
      Console.WriteLine("Yes");
   }
   else {
      Console.WriteLine("No");
   }
Pranay Rana
  • 175,020
  • 35
  • 237
  • 263