簡體   English   中英

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

[英]Equivalent of Math.Min & Math.Max for Dates?

獲取兩個日期之間的最小值(或最大值)的最快和最簡單的方法是什么? 日期是否有等效於 Math.Min (& Math.Max) 的值?

我想做類似的事情:

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

顯然,上面的 Math.Min 不起作用,因為它們是日期。

沒有內置的方法可以做到這一點。 您可以使用以下表達式:

(date1 > date2 ? date1 : date2)

找到兩者中的最大值。

您可以編寫一個通用方法來計算任何類型的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;
}

您也可以使用 LINQ:

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

DateTime 值沒有重載,但您可以獲取值包含的長值Ticks ,比較它們,然后從結果中創建一個新的 DateTime 值:

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

(請注意,DateTime 結構還包含Kind屬性,該屬性未保留在新值中。這通常不是問題;如果您比較不同種類的 DateTime 值,則無論如何比較都沒有意義。)

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

怎么樣:

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<T>IComparable的類型。

實際上,使用 LINQ,另一種選擇是:

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

如果你想使用 use Linq.Max()但更像是Math.Max ,你可以做一些類似這個非常短的表達式體的事情:

public static DateTime Max(params DateTime[] dates) => dates.Max();
[...]
var lastUpdatedTime = DateMath.Max(feedItemDateTime, assemblyUpdatedDateTime);
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);
    }

請注意,此測試將在格林威治以東失敗...

DateTime擴展方法怎么樣?

public static DateTime MaxOf(this DateTime instance, DateTime dateTime)
{
    return instance > dateTime ? instance : dateTime;
}

用法:

var maxDate = date1.MaxOf(date2);

將這兩個方法放在 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);
}

現在我們有了 LINQ,您可以使用您的兩個值(DateTimes、TimeSpans 等)創建一個數組,然后使用 .Max() 擴展方法。

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

它讀起來很好,它和 Max 一樣高效,並且可以重復使用 2 個以上的比較值。

下面擔心 .Kind 的整個問題是一個大問題……但我避免了這種情況,因為我從來沒有在當地時間工作過。 如果我對時間有重要的事情,我總是在 UTC 工作,即使這意味着需要做更多的工作才能到達那里。

我們可以使用 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()]);

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM