比较两个日期时间时忽略毫秒

时间:2011-08-11 15:49:41

标签: c# datetime c#-4.0

这可能是一个愚蠢的问题,但我似乎无法弄明白。我正在比较两个文件的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;
}

提前致谢

15 个答案:

答案 0 :(得分:82)

我建议你使用扩展方法:

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())

答案 1 :(得分:37)

创建一个新的DateTime值,并将毫秒组件设置为0:

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

答案 2 :(得分:35)

如果dt 非零微秒(毫秒的分数),则应该小心。仅将毫秒设置为零是不够的 要将millis和以下设置为零(并获得成功的比较),代码将为:

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

答案 3 :(得分:22)

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

答案 4 :(得分:12)

您可以减去它们,以获得TimeSpan

然后使用TimeSpan.totalSeconds()

答案 5 :(得分:6)

对于单个Truncate来说这是一种过度杀伤,但如果您有多种类型,可以使用下面的通用扩展方法执行此操作:

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
    }

答案 6 :(得分:3)

一种方法是创建新日期,将年,月,日,小时,分钟,秒输入构造函数。或者,您可以单独比较每个值。

答案 7 :(得分:1)

以太将其他日期时间的毫秒设置为零,或者从另一个日期时间中减去一个日期,然后检查生成的时间跨度的TotalMinutes属性。

答案 8 :(得分:1)

您可以创建一个扩展方法,将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;

答案 9 :(得分: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
    }
}

我以answer by Dean Chalk为基础进行效果比较,结果如下:

    在相同日期的情况下,
  • CompareWithTrimMilliseconds快一点

  • CompareWith比日期不相等更快

我的性能测试(在Console项目中运行)

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

答案 10 :(得分:1)

这是执行此操作的最简单方法。您可以根据需要控制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));

答案 11 :(得分:1)

您可以简单地将日期时间格式与您想要的格式一起使用,然后将其再次转换为日期时间,如下所示,

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

答案 12 :(得分:-1)

投射可排序的字符串并进行比较。简单而且运行良好。

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

答案 13 :(得分:-3)

截断时间最直接的方法是格式化它并解析你想要的单位:

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

答案 14 :(得分:-6)

不知道为什么几乎所有程序员都需要额外的行来从具有bool表达式的函数返回bool值。

代替

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

你可以随时使用

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

如果表达式为true,则返回true,否则返回false。