相当于Math.Min和Math.Max的日期?

haw*_*bsl 352 .net

在两个日期之间获得最小(或最大)值的最快捷最简单的方法是什么?是否有相当于Math.Min(&Math.Max)的日期?

我想做的事情如下:

 if (Math.Min(Date1, Date2) < MINIMUM_ALLOWED_DATE) {
      //not allowed to do this
 }
Run Code Online (Sandbox Code Playgroud)

显然上面的Math.Min不起作用,因为它们是日期.

Meh*_*ari 435

没有内置的方法来做到这一点.您可以使用以下表达式:

(date1 > date2 ? date1 : date2)
Run Code Online (Sandbox Code Playgroud)

找到两者中的最大值.

您可以编写一个通用方法来计算MinMax任何类型(假设Comparer<T>.Default设置得当):

public static T Max<T>(T first, T second) {
    if (Comparer<T>.Default.Compare(first, second) > 0)
        return first;
    return second;
}
Run Code Online (Sandbox Code Playgroud)

您也可以使用LINQ:

new[]{date1, date2, date3}.Max()
Run Code Online (Sandbox Code Playgroud)

  • 这实际上是应该接受的答案。 (7认同)
  • “LINQ”方式是最好的方式! (3认同)
  • @SerjSagan `LINQ` 是**最差**的方式。它的速度最慢并分配额外的内存。请参阅我关于基准测试的帖子:/sf/answers/5310899471/ (3认同)
  • 这并不总是与性能有关,事实上,如果性能不是问题,那么干净可读的代码就更为重要。 (3认同)

Guf*_*ffa 382

DateTime值没有重载,但您可以获取Ticks值包含的长值,比较它们,然后从结果中创建新的DateTime值:

new DateTime(Math.Min(Date1.Ticks, Date2.Ticks))
Run Code Online (Sandbox Code Playgroud)

(请注意,DateTime结构还包含一个Kind属性,该属性不会保留在新值中.这通常不是问题;如果比较不同类型的DateTime值,则无论如何比较都没有意义.)

  • @AndreasNiedermair:如果你要比较不同种类的日期,你不能直接比较它们.我在答案中已经涵盖了这一点. (9认同)
  • - ,你完全放弃原始`System.DateTime`实例的每个信息(除了刻度) (4认同)
  • @Iain:你总是*可以*比较它们,但是如果你比较那些不具有可比性的值,结果就没用了.它与任何其他无法比较的值相同,例如将公里距离与英里距离进行比较; 你可以很好地比较这些值,但这并不意味着什么. (4认同)
  • 在我看来,这对于Math.Min最接近单行替换/等效,但其他答案也很好,因为完整性 (2认同)
  • @AndreasNiedermair:`DateTime`值中唯一存在的信息是`Ticks`和`Kind`属性.所有其他属性都来自这些. (2认同)
  • -1用于手挥动的种类。如@ user450的答案所示,将两个时间都转换为UTC并在不丢弃信息的情况下进行安全比较是非常容易的。 (2认同)
  • 有趣的想法。不幸的是,1:DateTime.Kind 丢失了,2:它比 a (x &gt; y ? x : y) 涉及许多额外的计算 - 因为它是有效的,这不应该是公认的答案。 (2认同)

Mar*_*ell 35

怎么样:

public static T Min<T>(params T[] values)
{
    if (values == null) throw new ArgumentNullException("values");
    var comparer = Comparer<T>.Default;
    switch(values.Length) {
        case 0: throw new ArgumentException();
        case 1: return values[0];
        case 2: return comparer.Compare(values[0],values[1]) < 0
               ? values[0] : values[1];
        default:
            T best = values[0];
            for (int i = 1; i < values.Length; i++)
            {
                if (comparer.Compare(values[i], best) < 0)
                {
                    best = values[i];
                }
            }
            return best;
    }        
}
// overload for the common "2" case...
public static T Min<T>(T x, T y)
{
    return Comparer<T>.Default.Compare(x, y) < 0 ? x : y;
}
Run Code Online (Sandbox Code Playgroud)

适用于任何支持IComparable<T>或支持的类型IComparable.

实际上,使用LINQ,另一种选择是:

var min = new[] {x,y,z}.Min();
Run Code Online (Sandbox Code Playgroud)

  • 投票支持LINQ示例. (6认同)

小智 20

public static class DateTool
{
    public static DateTime Min(DateTime x, DateTime y)
    {
        return (x.ToUniversalTime() < y.ToUniversalTime()) ? x : y;
    }
    public static DateTime Max(DateTime x, DateTime y)
    {
        return (x.ToUniversalTime() > y.ToUniversalTime()) ? x : y;
    }
}
Run Code Online (Sandbox Code Playgroud)

这允许日期具有不同的"种类"并返回传入的实例(不返回从Ticks或Milliseconds构造的新DateTime).

[TestMethod()]
    public void MinTest2()
    {
        DateTime x = new DateTime(2001, 1, 1, 1, 1, 2, DateTimeKind.Utc);
        DateTime y = new DateTime(2001, 1, 1, 1, 1, 1, DateTimeKind.Local);

        //Presumes Local TimeZone adjustment to UTC > 0
        DateTime actual = DateTool.Min(x, y);
        Assert.AreEqual(x, actual);
    }
Run Code Online (Sandbox Code Playgroud)

请注意,此测试将在格林威治东部失败...

  • 为什么不直接删除 ToUniversalTime() 部分呢? (2认同)

Wil*_*ler 19

对于任何想知道之前提供的一些答案的性能的人,我对其中一些答案进行了基准测试。我使用三元运算符、LINQ 和 Math.max 来确定速度和内存的最佳解决方案。

三元

return a > b ? a : b;
Run Code Online (Sandbox Code Playgroud)
  • 平均速度:0.0198纳秒
  • 额外的内存分配:无
  • 垃圾收集时间:无

数学最大值

return new DateTime(Math.Max(a.Ticks, b.Ticks));
Run Code Online (Sandbox Code Playgroud)
  • 平均速度:2.4346 纳秒
  • 额外的内存分配:无
  • 垃圾收集时间:无

LINQ

return new[]{a, b}.Max();
Run Code Online (Sandbox Code Playgroud)
  • 平均速度:22.8383纳秒
  • 附加内存分配:72 字节
  • 垃圾收集时间:0.0057 纳秒
环境

.Net版本:6.0

C# 版本:10.0

配置:发布

参考

使用BenchmarkDotNet 0.13.5完成基准测试

日期时间比较基准


总长DR

三元运算符是迄今为止性能最高的方法。它的执行速度比亚军快 100 倍以上,并且不分配额外的内存。


Tos*_*shi 15

Linq.Min()/ Linq.Max()方法:

DateTime date1 = new DateTime(2000,1,1);
DateTime date2 = new DateTime(2001,1,1);

DateTime minresult = new[] { date1,date2 }.Min();
DateTime maxresult = new[] { date1,date2 }.Max(); 
Run Code Online (Sandbox Code Playgroud)


R. *_*ury 13

如果你想更像Math.Max,你可以做这样一个非常短的表达体:

public static DateTime Max(params DateTime[] dates) => dates.Max();
[...]
var lastUpdatedTime = DateMath.Max(feedItemDateTime, assemblyUpdatedDateTime);
Run Code Online (Sandbox Code Playgroud)


Oun*_*ess 7

扩展方法怎么样DateTime

public static DateTime MaxOf(this DateTime instance, DateTime dateTime)
{
    return instance > dateTime ? instance : dateTime;
}
Run Code Online (Sandbox Code Playgroud)

用法:

var maxDate = date1.MaxOf(date2);
Run Code Online (Sandbox Code Playgroud)