これはおそらく馬鹿げた質問ですが、私はそれを理解できないようです。 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;
}
前もって感謝します
ミリ秒コンポーネントを0に設定して、新しいDateTime値を作成します。
dt = dt.AddMilliseconds(-dt.Millisecond);
拡張メソッドを使用することをお勧めします。
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())
dt
に非ゼロマイクロ秒(ミリ秒の端数)がある場合は注意が必要です。ミリ秒のみをゼロに設定するだけでは十分ではありません。
ミリ秒以下をゼロに設定する(および正常な比較を取得する)ためのコードは次のようになります。
dt = dt.AddTicks(-dt.Ticks % TimeSpan.TicksPerSecond); // TimeSpan.TicksPerSecond=10000000
TimeSpan difference = dtNew - dtOrig;
if (difference >= TimeSpan.FromSeconds(1))
{
...
}
TimeSpan
を取得するために、それらを減算できます。
次にTimeSpan.totalSeconds()
を使用します
これは単一のトランケートでは過剰ですが、複数のさまざまなタイプがある場合は、以下の一般化された拡張方法を使用してこれを行うことができます。
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
}
1つの方法は、新しい日付を作成し、年、月、日、時間、分、秒をコンストラクターに入力することです。または、単純に各値を個別に比較することもできます。
イーサは、他の日時のミリ秒をゼロに設定するか、1つの日付を他の日付から減算して、結果のタイムスパンのTotalMinutes
プロパティを確認します。
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;
新しいDateTime
sを作成して関連のない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による回答 をパフォーマンス比較のベースとして採用しました。結果は次のとおりです。
日付が等しい場合、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();
}
これが最も簡単な方法です。必要に応じて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));