web-dev-qa-db-ja.com

2つの日時を比較するときにミリ秒を無視する

これはおそらく馬鹿げた質問ですが、私はそれを理解できないようです。 2つのファイルの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;
}

前もって感謝します

67
Eros Nikolli

ミリ秒コンポーネントを0に設定して、新しいDateTime値を作成します。

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

拡張メソッドを使用することをお勧めします。

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())
85
Dean Chalk

dt非ゼロマイクロ秒(ミリ秒の端数)がある場合は注意が必要です。ミリ秒のみをゼロに設定するだけでは十分ではありません。
ミリ秒以下をゼロに設定する(および正常な比較を取得する)ためのコードは次のようになります。

dt = dt.AddTicks(-dt.Ticks % TimeSpan.TicksPerSecond); // TimeSpan.TicksPerSecond=10000000
38
Peter Ivan
TimeSpan difference = dtNew - dtOrig;
if (difference >= TimeSpan.FromSeconds(1))
{
    ...
}
25
Paul Ruane

TimeSpanを取得するために、それらを減算できます。

次にTimeSpan.totalSeconds()を使用します

14
Sanjay Manohar

これは単一のトランケートでは過剰ですが、複数のさまざまなタイプがある場合は、以下の一般化された拡張方法を使用してこれを行うことができます。

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

より一般的なUse Extensionメソッド:

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

1つの方法は、新しい日付を作成し、年、月、日、時間、分、秒をコンストラクターに入力することです。または、単純に各値を個別に比較することもできます。

3
drharris

イーサは、他の日時のミリ秒をゼロに設定するか、1つの日付を他の日付から減算して、結果のタイムスパンのTotalMinutesプロパティを確認します。

1
Jonathan Wood

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
Bobby Borszich

新しいDateTimesを作成して関連のないDateTimeパーツをトリミングする代わりに、関連するパーツのみを比較します。

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

Dean Chalkによる回答 をパフォーマンス比較のベースとして採用しました。結果は次のとおりです。

  • 日付が等しい場合、CompareWithTrimMillisecondsよりも少し高速です

  • 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
ASh

これが最も簡単な方法です。必要に応じてprecisionを制御できます。

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

使い方は一目瞭然です

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