How do you compare DateTime objects using a specified tolerance in C#?

I usally use the TimeSpan.FromXXX methods to do something like this:

if((myDate - myOtherDate) > TimeSpan.FromSeconds(10))
{
   //Do something here
}

        if (Math.Abs(dt1.Subtract(dt2).TotalSeconds) < 1.0)

How about an extension method for DateTime to make a bit of a fluent interface (those are all the rage right?)

public static class DateTimeTolerance
{
    private static TimeSpan _defaultTolerance = TimeSpan.FromSeconds(10);
    public static void SetDefault(TimeSpan tolerance)
    {
        _defaultTolerance = tolerance;
    }

    public static DateTimeWithin Within(this DateTime dateTime, TimeSpan tolerance)
    {
        return new DateTimeWithin(dateTime, tolerance);
    }

    public static DateTimeWithin Within(this DateTime dateTime)
    {
        return new DateTimeWithin(dateTime, _defaultTolerance);
    }
}

This relies on a class to store the state and define a couple operator overloads for == and != :

public class DateTimeWithin
{
    public DateTimeWithin(DateTime dateTime, TimeSpan tolerance)
    {
        DateTime = dateTime;
        Tolerance = tolerance;
    }

    public TimeSpan Tolerance { get; private set; }
    public DateTime DateTime { get; private set; }

    public static bool operator ==(DateTime lhs, DateTimeWithin rhs)
    {
        return (lhs - rhs.DateTime).Duration() <= rhs.Tolerance;
    }

    public static bool operator !=(DateTime lhs, DateTimeWithin rhs)
    {
        return (lhs - rhs.DateTime).Duration() > rhs.Tolerance;
    }

    public static bool operator ==(DateTimeWithin lhs, DateTime rhs)
    {
        return rhs == lhs;
    }

    public static bool operator !=(DateTimeWithin lhs, DateTime rhs)
    {
        return rhs != lhs;
    }
}

Then in your code you can do:

DateTime d1 = DateTime.Now;
DateTime d2 = d1 + TimeSpan.FromSeconds(20);

if(d1 == d2.Within(TimeSpan.FromMinutes(1))) {
    // TRUE! Do whatever
}

The extension class also houses a default static tolerance so that you can set a tolerance for your whole project and use the Within method with no parameters:

DateTimeTolerance.SetDefault(TimeSpan.FromMinutes(1));

if(d1 == d2.Within()) {  // Uses default tolerance
    // TRUE! Do whatever
}

I have a few unit tests but that'd be a bit too much code for pasting here.


You need to remove the milliseconds component from the date object. One way is:

DateTime d = DateTime.Now;
d.Subtract(new TimeSpan(0, 0, 0, 0, d.Millisecond));

You can also subtract two datetimes

d.Subtract(DateTime.Now);

This will return a timespan object which you can use to compare the days, hours, minutes and seconds components to see the difference.