1

I am trying to write a simple LINQ query in which DateTime is compared to get the results. My requirement is that the DateTime has to be compared only till milliseconds and hence I have to apply formatter. The query is as follows

var availableValues = from value in AvailableValues
                      where DateTime.Compare(DateTime.ParseExact(value.Time.ToString("dd/MM/yyyy HH:mm:ss.fff"), "dd/MM/yyyy HH:mm:ss.fff", System.Globalization.CultureInfo.CurrentCulture),
                      DateTime.ParseExact(currentTime.ToString("dd/MM/yyyy HH:mm:ss.fff"), "dd/MM/yyyy HH:mm:ss.fff", System.Globalization.CultureInfo.CurrentCulture)) == 0
                      select value;

AvailableValues is huge collection and the above query is causing a perfomance hit.

It would be of great help if someone could suggest me a better way to achieve the expected result.

Subru
  • 343
  • 2
  • 13
  • 2
    You could start by only parsing the currentTime once. –  Mar 24 '16 at 10:18
  • So a date with a difference of 1 millisecond is not considered the same date? – Steve Mar 24 '16 at 10:32
  • 1
    This question and its answer could be a valid starting point to solve your problem http://stackoverflow.com/questions/1004698/how-to-truncate-milliseconds-off-of-a-net-datetime – Steve Mar 24 '16 at 10:35

2 Answers2

3
  1. Cache the value for the currentTime to avoid recalculating it for every comparison

  2. As far as I understand, you only want to compare including whole milliseconds (no fractions, no ticks). So you can create new DateTime values with only whole ms like that (if your query provider allows that):

    DateTime current = new DateTime(
        currentTime.Year, currentTime.Month, currentTime.Day, 
        currenTime.Hour, currentTime.Minute, currentTime.Second, currentTime.Kind).
        AddMilliseconds(currentTime.Millisecond);
    
    var availableValues = from value in AvailableValues
        where currentTime == new DateTime(
            value.Time.Year, value.Time.Month, value.Time.Day, 
            value.Time.Hour, value.Time.Minute, value.Time.Second, value.Time.Kind).
            AddMilliseconds(value.Time.Millisecond)
        select value;
    

This should be a lot faster than converting your DateTimes to string and back again.

René Vogt
  • 43,056
  • 14
  • 77
  • 99
2

My requirement is that the DateTime has to be compared only till milliseconds and hence I have to apply formatter.

Nope, you don't have to apply a formatter. Simply create a new date with an empty millisecond component. Instead of

DateTime.Compare(date1, date2)

use

DateTime.Compare(DropMilliseconds(date1), DropMilliseconds(date2))

or, since your are only interested in equality (not in the additional information that DateTime.Compare will give you):

DropMilliseconds(date1) == DropMilliseconds(date2)

with DropMilliseconds defined as follows (or any alternative implementation):

private static DateTime DropMilliseconds(DateTime dtm)
{
    return new DateTime(dtm.Year, dtm.Month, dtm.Day, 
                        dtm.Hour, dtm.Minute, dtm.Second, 
                        dtm.Kind);
}

If you are worried about the method call overhead, you can tell the compiler to aggressively inline it.

Community
  • 1
  • 1
Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • 1
    In his formatter he uses "fff", so he _does want_ to compare milliseconds, but only _whole_ milliseconds, no fractions or ticks or nanoseconds. – René Vogt Mar 24 '16 at 10:44
  • @RenéVogt: Good point. The question can be interpreted either way (since "until" can be [inclusive or exclusive](http://ell.stackexchange.com/q/33340/27863)), so I'll leave my answer - it might help someone else finding this question. In any case, the principal solution is the same: [Rounding to milliseconds](http://stackoverflow.com/q/2872444/87698) is even simpler than stripping them. Oh, and +1 to your answer! – Heinzi Mar 24 '16 at 10:49