Ignore milliseconds when comparing two datetimes

C#DatetimeC# 4.0

C# Problem Overview


This is probably a dumb question, but I cannot seem to figure it out. I am comparing the LastWriteTime of two files, however it is always failing because the file I downloaded off the net always has milliseconds set at 0, and my original file has an actual value. Is there a simple way to ignore the milliseconds when comparing?

Here's my function:

//compare file's dates
public bool CompareByModifiedDate(string strOrigFile, string strDownloadedFile)
{
     DateTime dtOrig = File.GetLastWriteTime(strOrigFile);
     DateTime dtNew = File.GetLastWriteTime(strDownloadedFile);
            
     if (dtOrig == dtNew)
        return true;
     else
        return false;
}

Thanks in advance

C# Solutions


Solution 1 - C#

I recommend you use an extension method:

public static DateTime TrimMilliseconds(this DateTime dt)
{
    return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, 0, dt.Kind);
}

then its just:

if (dtOrig.TrimMilliseconds() == dtNew.TrimMilliseconds())

Solution 2 - C#

Care should be taken, if dt has non-zero microseconds (fractions of millis). Setting only milliseconds to zero is not enough.
To set millis and below to zero (and get a succesfull comparison), the code would be:

dt = dt.AddTicks(-dt.Ticks % TimeSpan.TicksPerSecond); // TimeSpan.TicksPerSecond=10000000

Solution 3 - C#

Create a new DateTime value with the milliseconds component set to 0:

dt = dt.AddMilliseconds(-dt.Millisecond);

Solution 4 - C#

TimeSpan difference = dtNew - dtOrig;
if (difference >= TimeSpan.FromSeconds(1))
{
    ...
}

Solution 5 - C#

You can subtract them, to get a TimeSpan.

Then use TimeSpan.totalSeconds()

Solution 6 - C#

This is overkill for a single Truncate, but if you have several and of various types you could do this using the generalized Extension Method below:

DateTime dtSecs = DateTime.Now.TruncateTo(Extensions.DateTruncate.Second);
DateTime dtHrs  = DateTime.Now.TruncateTo(Extensions.DateTruncate.Hour);

More general Use Extension method:

    public static DateTime TruncateTo(this DateTime dt, DateTruncate TruncateTo)
    {
        if (TruncateTo == DateTruncate.Year)
            return new DateTime(dt.Year, 0, 0);
        else if (TruncateTo == DateTruncate.Month)
            return new DateTime(dt.Year, dt.Month, 0);
        else if (TruncateTo == DateTruncate.Day)
            return new DateTime(dt.Year, dt.Month, dt.Day);
        else if (TruncateTo == DateTruncate.Hour)
            return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, 0, 0);
        else if (TruncateTo == DateTruncate.Minute)
            return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0);
        else 
            return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second);
        
    }
    public enum DateTruncate
    {
        Year,
        Month,
        Day,
        Hour,
        Minute,
        Second
    }

Solution 7 - C#

Here is the simplest way of doing this. You can control precision as you want.

bool AreEqual(DateTime a, DateTime b, TimeSpan precision)
{
	return Math.Abs((a - b).TotalMilliseconds) < precision.TotalMilliseconds;
}

and usage is pretty self-explanatory

var _ = AreEqual(a, b, precision: TimeSpan.FromSeconds(1));

Solution 8 - C#

One way would be to create new dates, inputting the year, month, day, hour, minute, second into the constructor. Alternatively, you could simply compare each value separately.

Solution 9 - C#

Ether set the milliseconds in your other datetime to zero, or subtract one date from the other and just check the TotalMinutes property of the resulting time span.

Solution 10 - C#

You could create an extension method that would set the milliseconds to zero for a DateTime object

public static DateTime ZeroMilliseconds(this DateTime value) {
  return new DateTime(value.Year, value.Month, value.Day, 
    value.Hours, value.Minutes, value.Seconds);
}

Then in your function

 if (dtOrig.ZeroMilliseconds() == dtNew.ZeroMilliseconds())
        return true;
     else
        return false;

Solution 11 - C#

instead of trimming unrelevant DateTime parts via creating new DateTimes, compare only relevant parts:

public static class Extensions
{
    public static bool CompareWith(this DateTime dt1, DateTime dt2)
    {
        return
            dt1.Second == dt2.Second && // 1 of 60 match chance
            dt1.Minute == dt2.Minute && // 1 of 60 chance
            dt1.Day == dt2.Day &&       // 1 of 28-31 chance
            dt1.Hour == dt2.Hour &&     // 1 of 24 chance
            dt1.Month == dt2.Month &&   // 1 of 12 chance
            dt1.Year == dt2.Year;       // depends on dataset
    }
}

I took answer by Dean Chalk as base for performance comparison, and results are:

  • CompareWith is a bit faster than TrimMilliseconds in case of equal dates

  • CompareWith is a faster than dates are not equal

my perf test (run in Console project)

static void Main(string[] args)
{
    var dtOrig = new DateTime(2018, 03, 1, 10, 10, 10);
    var dtNew = dtOrig.AddMilliseconds(100);

    //// perf run for not-equal dates comparison
    //dtNew = dtNew.AddDays(1);
    //dtNew = dtNew.AddMinutes(1);

    int N = 1000000;

    bool isEqual = false;

    var sw = Stopwatch.StartNew();
    for (int i = 0; i < N; i++)
    {
        // TrimMilliseconds comes from 
        // https://stackoverflow.com/a/7029046/1506454 
        // answer by Dean Chalk
        isEqual = dtOrig.TrimMilliseconds() == dtNew.TrimMilliseconds();
    }
    var ms = sw.ElapsedMilliseconds;
    Console.WriteLine("DateTime trim: " + ms + " ms");

    sw = Stopwatch.StartNew();
    for (int i = 0; i < N; i++)
    {
        isEqual = dtOrig.CompareWith(dtNew);
    }
    ms = sw.ElapsedMilliseconds;
    Console.WriteLine("DateTime partial compare: " + ms + " ms");

    Console.ReadKey();
}

Solution 12 - C#

Simply you can use datetime format with the format you want, and convert it again to datetime as below,

//compare file's dates
        
        String format1 = @"yyyy-MM-dd HH:mm:ss"; // you also can avoid seconds if you want

        public bool CompareByModifiedDate(string strOrigFile, string strDownloadedFile)
        {
            
            //.here we will use the format

            DateTime dtOrig = Convert.ToDateTime(File.GetLastWriteTime(strOrigFile).ToString(format1));
            DateTime dtNew = Convert.ToDateTime(File.GetLastWriteTime(strDownloadedFile).ToString(format1));

            if (dtOrig == dtNew)
                return true;
            else
                return false;
        }

Solution 13 - C#

cast sortable strings and compare. simple and run well.

    return string.Compare(dtOrig.ToString("s"), dtNew.ToString("s"), 
StringComparison.Ordinal) == 0;
   

Solution 14 - C#

The most straightforward way to truncate time is to format it and parse on the units that you want:

var myDate = DateTime.Parse(DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss"));

DOK's method re-written

public bool CompareByModifiedDate(string strOrigFile, string strDownloadedFile)
	{
	     DateTime dtOrig = DateTime.Parse(File.GetLastWriteTime(strOrigFile).ToString("MM/dd/yyyy hh:mm:ss"));
	     DateTime dtNew = DateTime.Parse(File.GetLastWriteTime(strDownloadedFile).ToString("MM/dd/yyyy hh:mm:ss"));
	
	     if (dtOrig == dtNew)
	        return true;
	     else
	        return false;
	}

Solution 15 - C#

Don't know why almost all programmers needs extra lines to return a bool value from a function with a bool expression.

instead

if (dtOrig.ZeroMilliseconds() == dtNew.ZeroMilliseconds())
    return true;
 else
    return false;

you can always just use

return dtOrig.ZeroMilliseconds() == dtNew.ZeroMilliseconds()

if the expression is true it returns true else false.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEros NikolliView Question on Stackoverflow
Solution 1 - C#Dean ChalkView Answer on Stackoverflow
Solution 2 - C#Peter IvanView Answer on Stackoverflow
Solution 3 - C#dtbView Answer on Stackoverflow
Solution 4 - C#Paul RuaneView Answer on Stackoverflow
Solution 5 - C#Sanjay ManoharView Answer on Stackoverflow
Solution 6 - C#deepee1View Answer on Stackoverflow
Solution 7 - C#Vladimir GaevoyView Answer on Stackoverflow
Solution 8 - C#drharrisView Answer on Stackoverflow
Solution 9 - C#Jonathan WoodView Answer on Stackoverflow
Solution 10 - C#Bobby BorszichView Answer on Stackoverflow
Solution 11 - C#AShView Answer on Stackoverflow
Solution 12 - C#Ahmed FekryView Answer on Stackoverflow
Solution 13 - C#Nuri YILMAZView Answer on Stackoverflow
Solution 14 - C#M. SmithView Answer on Stackoverflow
Solution 15 - C#Mickey MouseView Answer on Stackoverflow