如何在 C# 中比较两个日期的年、月、日、时、分、秒?

How to compare two dates in C# on just year, month, day, hour, minute, second?

我有两个日期,我只想确保它们在这 6 个字段上匹配: 年月日时分秒

我注意到,如果我对这些字段进行匹配的简单相等 == 比较 if(d1 == d2),我仍然会得到 'false'。我假设这与引擎盖下与刻度、毫秒等相关的其他字段有关。我如何忽略所有内容并确保它们与上面的 6 个字段匹配?

我已经创建了下面的原型函数,但对我来说,这对于生产级代码来说感觉很业余且效率低下。此外,date1 必须是可为空的日期时间。

有没有其他人有更好的建议?

    private static bool DatesAreEqual(DateTime date1, DateTime date2)
    {

        var d1 = new DateTime(date1.Year, date1.Month, date1.Day,
                    date1.Hour, date1.Minute, date1.Second);

        var d2 = new DateTime(date2.Year, date2.Month, date2.Day,
                    date2.Hour, date2.Minute, date2.Second);

        return d1 == d2;
    }

这可能会稍微快一些:

var sameDateTime = ((date1 - date2).Milliseconds < 1000);

您可以删除日期的小数部分(请注意,小数部分比毫秒长):

DateTime date = DateTime.Now;

// 28 02 2022 22:19:56.3704625 
Console.WriteLine($"{date:dd MM yyyy HH:mm:ss.fffffff}"); 

date -= TimeSpan.FromTicks(date.Ticks % 10_000_000);

// 28 02 2022 22:19:56.0000000
Console.WriteLine($"{date:dd MM yyyy HH:mm:ss.fffffff}");

代码:

DateTime date1 = ...
DateTime date2 = ...

...

if (date1 - TimeSpan.FromTicks(date1.Ticks % 10_000_000) == 
    date2 - TimeSpan.FromTicks(date2.Ticks % 10_000_000)) {
  //TODO: Relevant code here
}

您可以实施 扩展 class 以保持主要代码更短和更易读:

public partial static class DateTimeExtensions {
  public static DateTime TrimToSeconds(this DateTime value) => 
    value - TimeSpan.FromTicks(value.Ticks % 10_000_000)
}

然后

DateTime date1 = ...
DateTime date2 = ...

...

if (date1.TrimToSeconds() == date2.TrimToSeconds()) {
  //TODO: Relevant code here
}

如果您检查 TimeSpam,我们有 TimeSpan.TicksPerSecond,这是您希望相同的最小值(秒),因此我们将该部分重置为零,并使用滴答进行比较(即更快)如:

pubic static bool DatesAreEqual(DateTime d1, DateTime d2)
{
    return (d1.Ticks - (d1.Ticks % TimeSpan.TicksPerSecond)) == (d2.Ticks - (d2.Ticks % TimeSpan.TicksPerSecond));
}

通过这种方式,您只需比较一些数字,而且速度更快。

不止于此

在上述代码的基础上,我还制作了另外两个函数,选择了 Precision 和 Equal,或者 Compare 函数

public enum DateTimeComparePrecision : long
{
    Millisecond  = TimeSpan.TicksPerMillisecond,
    Second = TimeSpan.TicksPerSecond,
    Minute = TimeSpan.TicksPerMinute,
    Hour = TimeSpan.TicksPerHour,
    Day = TimeSpan.TicksPerDay,
}


public static bool DatesAreEqual(DateTime d1, DateTime d2, DateTimeComparePrecision Precision)
{
    return (d1.Ticks - (d1.Ticks % (long)Precision)) == (d2.Ticks - (d2.Ticks % (long)Precision));
}        


public static int DatesCompare(DateTime d1, DateTime d2, DateTimeComparePrecision Precision)
{
    long Day1 = (d1.Ticks - (d1.Ticks % (long)Precision));
    long Day2 = (d2.Ticks - (d2.Ticks % (long)Precision));

    if (Day2 > Day1) 
        return 1;            

    if (Day2 < Day1)            
        return -1;            

    return 0;
}

简单的视觉测试

DateTime NowIs = DateTime.UtcNow;
Console.WriteLine($"{NowIs:dd MM yyyy HH:mm:ss.fffffff}");

DateTime d1 = new DateTime((NowIs.Ticks - (NowIs.Ticks % TimeSpan.TicksPerMillisecond)));
Console.WriteLine($"{d1:dd MM yyyy HH:mm:ss.fffffff}");

d1 = new DateTime((NowIs.Ticks - (NowIs.Ticks % TimeSpan.TicksPerSecond)));
Console.WriteLine($"{d1:dd MM yyyy HH:mm:ss.fffffff}");

d1 = new DateTime((NowIs.Ticks - (NowIs.Ticks % TimeSpan.TicksPerMinute)));
Console.WriteLine($"{d1:dd MM yyyy HH:mm:ss.fffffff}");

d1 = new DateTime((NowIs.Ticks - (NowIs.Ticks % TimeSpan.TicksPerHour)));
Console.WriteLine($"{d1:dd MM yyyy HH:mm:ss.fffffff}");

d1 = new DateTime((NowIs.Ticks - (NowIs.Ticks % TimeSpan.TicksPerDay)));
Console.WriteLine($"{d1:dd MM yyyy HH:mm:ss.fffffff}");

输出

01 03 2022 12:51:26.7237323
01 03 2022 12:51:26.7230000
01 03 2022 12:51:26.0000000
01 03 2022 12:51:00.0000000
01 03 2022 12:00:00.0000000
01 03 2022 00:00:00.0000000