我正在比较两个文件的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;
}
我建议你使用扩展方法:
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
创建一个新的 DateTime 值,并将毫秒部分设置为 0:
dt = dt.AddMilliseconds(-dt.Millisecond);
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);
更通用的使用扩展方法:
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
}
这是最简单的方法。您可以随心所欲地控制
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));
一种方法是创建新日期,将年、月、日、小时、分钟、秒输入到构造函数中。或者,您可以简单地分别比较每个值。
不要通过创建新的
DateTime
来修剪不相关的 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();
}
将其他日期时间中的毫秒设置为零,或从另一个日期中减去一个日期,然后检查结果时间跨度的
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;
您可以使用您想要的格式的日期时间格式,然后将其再次转换为日期时间,如下所示,
//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;
}
修剪的
DateTime
比较的通用形式可以写成如下:
static bool TrimmedEquals(DateTime dt1, DateTime dt2, long delta)
{
return Math.Abs((dt1 - dt2).Ticks) < delta;
}
TimeSpan
Struct
有许多常量字段,可以用作 delta
。
或者,可以使用带有
TimeSpan
参数的方法:
static bool TrimmedEquals(DateTime dt1, DateTime dt2, TimeSpan delta)
{
return Math.Abs((dt1 - dt2).Ticks) < delta.Ticks;
}
如果您想进行内联比较:
if (Math.Abs((dtNew - dtOrig).Ticks) < TimeSpan.TicksPerSecond)
{
// Dates are equal
}
else
{
// Dates are not equal
}
测试 2 个
DateTime
的输出:
DateTime dtOrig = DateTime.Now;
DateTime dtNew = DateTime.Now.AddMilliseconds(1);
Console.WriteLine($"Original Date: {dtOrig:O}");
Console.WriteLine($"Original Date (ticks): {dtOrig.Ticks}");
Console.WriteLine($"New Date: {dtNew:O}");
Console.WriteLine($"New Date (ticks): {dtNew.Ticks}");
Console.WriteLine();
long[] deltas =
{
TimeSpan.TicksPerMicrosecond,
TimeSpan.TicksPerMillisecond,
TimeSpan.TicksPerSecond,
TimeSpan.TicksPerMinute,
TimeSpan.TicksPerHour,
TimeSpan.TicksPerDay,
};
Console.WriteLine("Test 1");
Console.WriteLine("dt1: dtOrig");
Console.WriteLine("dt2: dtNew");
foreach (long delta in deltas)
{
if (TrimmedEquals(dtOrig, dtNew, delta))
{
Console.WriteLine($"Dates are equal with delta: {delta}");
}
else
{
Console.WriteLine($"Dates are not equal with delta: {delta}");
}
}
Console.WriteLine();
Console.WriteLine("Test 2");
Console.WriteLine("dt1: dtNew");
Console.WriteLine("dt2: dtOrig");
foreach (long delta in deltas)
{
if (TrimmedEquals(dtNew, dtOrig, delta))
{
Console.WriteLine($"Dates are equal with delta: {delta}");
}
else
{
Console.WriteLine($"Dates are not equal with delta: {delta}");
}
}
// Original Date: 2024-12-19T12:28:04.0732065+01:00
// Original Date (ticks): 638702080840732065
// New Date: 2024-12-19T12:28:04.0805347+01:00
// New Date (ticks): 638702080840805347
//
// Test 1
// dt1: dtOrig
// dt2: dtNew
// Dates are not equal with delta: 10
// Dates are not equal with delta: 10000
// Dates are equal with delta: 10000000
// Dates are equal with delta: 600000000
// Dates are equal with delta: 36000000000
// Dates are equal with delta: 864000000000
//
// Test 2
// dt1: dtNew
// dt2: dtOrig
// Dates are not equal with delta: 10
// Dates are not equal with delta: 10000
// Dates are equal with delta: 10000000
// Dates are equal with delta: 600000000
// Dates are equal with delta: 36000000000
// Dates are equal with delta: 864000000000
投射可排序字符串并进行比较。简单且运行良好。
return string.Compare(dtOrig.ToString("s"), dtNew.ToString("s"),
StringComparison.Ordinal) == 0;
截断时间最直接的方法是对其进行格式化并解析您想要的单位:
var myDate = DateTime.Parse(DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss"));
DOK的方法重写了
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;
}
不知道为什么几乎所有程序员都需要额外的行来从具有 bool 表达式的函数返回 bool 值。
相反
if (dtOrig.ZeroMilliseconds() == dtNew.ZeroMilliseconds())
return true;
else
return false;
你可以随时使用
return dtOrig.ZeroMilliseconds() == dtNew.ZeroMilliseconds()
如果表达式为 true,则返回 true,否则返回 false。