Игнорировать миллисекунды при сравнении двух дат - PullRequest
65 голосов
/ 11 августа 2011

Это, вероятно, глупый вопрос, но я не могу понять это. Я сравниваю LastWriteTime двух файлов, однако он всегда терпит неудачу, потому что для файла, который я скачал из сети, всегда заданы миллисекунды, равные 0, а мой исходный файл имеет фактическое значение. Есть ли простой способ игнорировать миллисекунды при сравнении?

Вот моя функция:

//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;
}

Заранее спасибо

Ответы [ 13 ]

82 голосов
/ 11 августа 2011

Я рекомендую использовать метод расширения:

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);
}

, тогда его просто:

if (dtOrig.TrimMilliseconds() == dtNew.TrimMilliseconds())
37 голосов
/ 11 августа 2011

Создайте новое значение DateTime с компонентом миллисекунд, установленным в 0:

dt = dt.AddMilliseconds(-dt.Millisecond);
36 голосов
/ 19 июля 2012

Следует соблюдать осторожность, если dt имеет ненулевые микросекунды (доли миллис). Недостаточно установить только ноль миллисекунд.
Чтобы установить миллис и ниже на ноль (и получить успешное сравнение), код будет:

dt = dt.AddTicks(-dt.Ticks % TimeSpan.TicksPerSecond); // TimeSpan.TicksPerSecond=10000000
23 голосов
/ 11 августа 2011
TimeSpan difference = dtNew - dtOrig;
if (difference >= TimeSpan.FromSeconds(1))
{
    ...
}
12 голосов
/ 11 августа 2011

Вы можете вычесть их, чтобы получить TimeSpan.

Затем используйте TimeSpan.totalSeconds()

6 голосов
/ 11 августа 2011

Это избыточно для одного усечения, но если у вас есть несколько различных типов, вы можете сделать это, используя обобщенный метод расширения ниже:

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

Более общее использование Метод расширения:

    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
    }
3 голосов
/ 11 августа 2011

Один из способов - создать новые даты, введя год, месяц, день, час, минуту, секунду в конструктор. В качестве альтернативы, вы можете просто сравнить каждое значение отдельно.

1 голос
/ 08 марта 2018

вместо обрезки нерелевантных деталей DateTime путем создания новых DateTime s, сравнивайте только релевантные детали:

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
    }
}

Я взял ответ Дина Чела за основу для сравнения производительности, и результаты:

  • CompareWith немного быстрее, чем TrimMilliseconds в случае равных дат

  • CompareWith быстрее, чем даты не равны

мой тест производительности (запущен в консольном проекте)

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();
}
1 голос
/ 11 августа 2011

Вы можете создать метод расширения, который установит нулевые миллисекунды для объекта DateTime

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

Тогда в твоей функции

 if (dtOrig.ZeroMilliseconds() == dtNew.ZeroMilliseconds())
        return true;
     else
        return false;
1 голос
/ 11 августа 2011

Ether установите миллисекунды в другое время даты на ноль или вычтите одну дату из другой и просто проверьте свойство TotalMinutes результирующего промежутка времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...