日期的 Math.Min 和 Math.Max 等价物?

Posted

技术标签:

【中文标题】日期的 Math.Min 和 Math.Max 等价物?【英文标题】:Equivalent of Math.Min & Math.Max for Dates? 【发布时间】:2010-12-31 09:58:45 【问题描述】:

获取两个日期之间的最小值(或最大值)的最快和最简单的方法是什么?日期是否有等效于 Math.Min (& Math.Max) 的方法?

我想做这样的事情:

 if (Math.Min(Date1, Date2) < MINIMUM_ALLOWED_DATE) 
      //not allowed to do this
 

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

【问题讨论】:

【参考方案1】:

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

(date1 > date2 ? date1 : date2)

求两者中的最大值。

您可以编写一个通用方法来计算任何类型的MinMax(前提是Comparer&lt;T&gt;.Default 设置得当):

public static T Max<T>(T first, T second) 
    if (Comparer<T>.Default.Compare(first, second) > 0)
        return first;
    return second;

你也可以使用 LINQ:

new[]date1, date2, date3.Max()

【讨论】:

【参考方案2】:

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

new DateTime(Math.Min(Date1.Ticks, Date2.Ticks))

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

【讨论】:

在我看来,这似乎最接近 Math.Min 的单行替换/等效项,但为了完整性,其他答案也很棒 -,您完全失去了原始System.DateTime-instance 的所有信息(除了记号) @AndreasNiedermair:如果您要比较不同类型的日期,无论如何您都不能直接比较它们。我已经在答案中介绍了这一点。 @Iain:你总是可以比较它们,但是如果你比较不可比较的值,结果是没有用的。它与任何其他不可比较的值相同,例如比较以公里为单位的距离和以英里为单位的距离;您可以很好地比较这些值,但这并不意味着什么。 -1 对 Kind 挥手致意。如@user450 的回答所示,很容易将两个时间都转换为 UTC 并安全地比较它们而不会丢弃信息。【参考方案3】:

怎么样:

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;

适用于支持IComparable&lt;T&gt;IComparable 的任何类型。

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

var min = new[] x,y,z.Min();

【讨论】:

第一种方法,空检查后可以是return values.Min();【参考方案4】:

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

【讨论】:

【参考方案5】:

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

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

【讨论】:

【参考方案6】:
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;
    

这允许日期具有不同的“种类”并返回传入的实例(不返回由 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);
    

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

【讨论】:

为什么不直接删除 ToUniversalTime() 部分?【参考方案7】:

DateTime 扩展方法怎么样?

public static DateTime MaxOf(this DateTime instance, DateTime dateTime)

    return instance > dateTime ? instance : dateTime;

用法:

var maxDate = date1.MaxOf(date2);

【讨论】:

我更喜欢将其用作DateTime.MaxOf(dt1, dt2),但我不知道该怎么做... @ZachSmith 您不能重载 DateTime 类,因为它不是部分的。也许我们可以使用 DateTimeHelper.Max(dt1, dt2) @shtse8 - 重载是什么意思?我正在考虑添加扩展方法。但后来了解到,如果没有实例化实例,就无法做到这一点。听起来您是在说添加扩展方法是一种重载形式?我从来没有考虑过..这是正确的吗?现在我想起来了……重载到底是什么意思? @ZachSmith 哦,我以为您正在添加一个名为“DateTime.MaxOf(dt1, dt2)”的扩展名,就像基于 DateTime 静态成员的“DateTime.Now”一样。【参考方案8】:

将这两个方法放在一个 Utility 类中,并使用它们来获取任意数量的 DateTimes 的 Min/Max:

    public static DateTime Min(params DateTime[] dates)
    
        if (dates.Length == 1) return dates[0];

        long minTicks = dates[0].Ticks;

        for (int i = 1; i < dates.Length; i++)
        
            minTicks = Math.Min(minTicks, dates[i].Ticks);
        

        return new DateTime(minTicks);
    

    public static DateTime Max(params DateTime[] dates)
    
        if (dates.Length == 1) return dates[0];

        long maxTicks = dates[0].Ticks;

        for (int i = 1; i < dates.Length; i++)
        
            maxTicks = Math.Max(maxTicks, dates[i].Ticks);
        

        return new DateTime(maxTicks);
    

【讨论】:

【参考方案9】:

现在我们有了 LINQ,您可以使用两个值(DateTimes、TimeSpans 等)创建一个数组,然后使用 .Max() 扩展方法。

var values = new[]  Date1, Date2 ; 
var max = values.Max(); 

它读起来很好,它的效率与 Max 一样高,并且可重复用于 2 个以上的比较值。

下面担心 .Kind 的整个问题是个大问题……但我避免了这种情况,因为我从来没有在当地时间工作过。如果我有重要的时间方面的事情,我总是在 UTC 工作,即使这意味着需要更多的工作才能到达那里。

【讨论】:

我的答案副本【参考方案10】:

我们可以使用 Date.parse() 将日期转换为 Number 原语,然后我们可以使用 Math.min() 和 Math.max() 进行处理和存储。使用该原语,我们可以以我们想要的任何格式进行渲染。 这是一个 2-3 步的过程,但我们几乎消除了获得时髦结果的风险。

const unixTimeZero = Date.parse('01 Jan 1970 00:00:00 GMT');
const javascriptRelease = Date.parse('04 Dec 1995 00:12:00 GMT');
const today = Date.parse(new Date());
const d1 = Date.parse(new Date("2004-02-01"));
const d2 = Date.parse(new Date("2017-01"));
const d3 = Date.parse(new Date("2018"))
const t = [unixTimeZero, d1, d2, d3, today, javaScriptRelease];
const min = Math.min(...t)
const max = Math.max(...t)
console.log(unixTimeZero); // expected output: 0
console.log(javaScriptRelease); // expected output: 818035920000
console.log(today);
console.log(t);
console.log(["unixMin: " + min, "earliestDate: " + new Date(min).toUTCString()]);
console.log(["unixMax: " + max, "latestDate: " + new Date(max).toDateString()]);

【讨论】:

问题是关于C#的 我的错.. 没看到。我很笨【参考方案11】:
// Two different dates
var date1 = new Date(2013, 05, 13); 
var date2 = new Date(2013, 04, 10) ;
// convert both dates in milliseconds and use Math.min function
var minDate = Math.min(date1.valueOf(), date2.valueOf());
// convert minDate to Date
var date = new Date(minDate); 

http://jsfiddle.net/5CR37/

【讨论】:

很好的建议(真的),但没有描述很难找到为什么它是好的。请描述诀窍在哪里。没有描述,它只是一段代码,而不是答案。 问题被标记为 .NET 而不是 Javascript 抱歉,没有注意到 .NET。无论如何,我们可以在客户端找到最小日期并将其发送到服务器。 你假设我们说的是asp,这不一定对。在客户端上计算差异也是非常愚蠢的,因为存在更多风险(禁用 JavaScript),它会产生不必要的流量并且(取决于网络速度)会变慢 创建一个运行在node.js中的datecomparison微服务,然后你就可以调用它来回答原问题了

以上是关于日期的 Math.Min 和 Math.Max 等价物?的主要内容,如果未能解决你的问题,请参考以下文章

利用Math.max/min获取数组最大最小值

Math对象(min()-max()-ceil()-floor()-round()和abs())

javascript Math.min Math.max

Math.min() / Math.max() 使用方法

js-20170804-Math对象

math对象的主要方法