Äquivalent von Math.Min & Math.Max ​​für Termine?

369

Was ist der schnellste und einfachste Weg, um den Min- (oder Max-) Wert zwischen zwei Daten zu ermitteln? Gibt es ein Äquivalent zu Math.Min (& Math.Max) für Daten?

Ich möchte so etwas tun wie:

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

Offensichtlich funktioniert die obige Math.Min nicht, weil es sich um Daten handelt.

hawbsl
quelle

Antworten:

416

Es gibt keine Überladung für DateTime-Werte, aber Sie können den langen Wert Ticks, den die Werte enthalten, abrufen, vergleichen und dann aus dem Ergebnis einen neuen DateTime-Wert erstellen:

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

(Beachten Sie, dass die DateTime-Struktur auch eine KindEigenschaft enthält , die im neuen Wert nicht beibehalten wird. Dies ist normalerweise kein Problem. Wenn Sie DateTime-Werte verschiedener Art vergleichen, ist der Vergleich ohnehin nicht sinnvoll.)

Guffa
quelle
2
Dies schien mir am nächsten an einem einzeiligen Ersatz / Äquivalent für Math.Min zu sein, aber die anderen Antworten waren der Vollständigkeit
halber auch
6
-, Sie verlieren vollständig alle Informationen (außer den Zecken) der ursprünglichen System.DateTime-Instanz
Andreas Niedermair
9
@AndreasNiedermair: Wenn Sie Daten verschiedener Art vergleichen, können Sie sie sowieso nicht einfach direkt vergleichen. Ich habe dies bereits in der Antwort behandelt.
Guffa
4
@Iain: Sie können sie immer vergleichen, aber wenn Sie Werte vergleichen, die nicht vergleichbar sind, ist das Ergebnis nutzlos. Es ist genauso wie bei allen anderen Werten, die nicht vergleichbar sind, z. B. beim Vergleich einer Entfernung in Kilometern mit einer Entfernung in Meilen. Sie können die Werte gut vergleichen, aber es hat nichts zu bedeuten.
Guffa
4
-1 für Handwinken über Kind. Wie in der Antwort von @ user450 gezeigt, ist es recht einfach, beide Male in UTC zu konvertieren und sicher zu vergleichen, ohne Informationen zu verwerfen.
Piedar
484

Es gibt keine eingebaute Methode, um das zu tun. Sie können den Ausdruck verwenden:

(date1 > date2 ? date1 : date2)

um das Maximum der beiden zu finden.

Sie können eine generische Methode zur Berechnung Minoder Maxfür jeden Typ schreiben (vorausgesetzt, dies Comparer<T>.Defaultist entsprechend eingestellt):

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

Sie können auch LINQ verwenden:

new[]{date1, date2, date3}.Max()
Mehrdad Afshari
quelle
15
Dies ist eigentlich die Antwort, die es verdient, akzeptiert zu werden.
Larry
38

Wie wäre es mit:

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

Funktioniert mit jedem Typ, der IComparable<T>oder unterstützt IComparable.

Mit LINQ ist eine weitere Alternative:

var min = new[] {x,y,z}.Min();
Marc Gravell
quelle
6
Stimmen Sie für das LINQ-Beispiel ab.
Oundless
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;
    }
}

Dies ermöglicht es den Datumsangaben, unterschiedliche 'Arten' zu haben, und gibt die übergebene Instanz zurück (ohne eine neue aus Ticks oder Millisekunden erstellte DateTime zurückzugeben).

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

Beachten Sie, dass dieser Test östlich von Greenwich fehlschlagen würde ...

user450
quelle
Warum nicht einfach den Teil ToUniversalTime () löschen?
David Thielen
18

Linq.Min()/ Linq.Max()Ansatz:

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(); 
Toshi
quelle
17

Wenn Sie es eher wie Math.Max ​​nennen möchten, können Sie so etwas wie diesen sehr kurzen Ausdruckskörper tun:

public static DateTime Max(params DateTime[] dates) => dates.Max();
[...]
var lastUpdatedTime = DateMath.Max(feedItemDateTime, assemblyUpdatedDateTime);
R. Salisbury
quelle
Oh, das ist Genie! Auf diese Weise muss ich nicht jedes Mal vergleichen, nur einmal, nachdem ich mit den Daten fertig bin. Vielen Dank!
Tfrascaroli
Dies ist eine sehr elegante Lösung
pberggreen
2

Wie wäre es mit einer DateTimeErweiterungsmethode?

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

Verwendungszweck:

var maxDate = date1.MaxOf(date2);
Oundless
quelle
Ich würde es lieber als verwenden DateTime.MaxOf(dt1, dt2), aber ich weiß nicht, wie ich das machen soll ...
Zach Smith
@ZachSmith Sie können die DateTime-Klasse nicht überladen, da sie nicht partiell ist. Vielleicht können wir DateTimeHelper.Max (dt1, dt2)
shtse8
@ shtse8 - was meinst du mit Überladung? Ich dachte darüber nach, eine Erweiterungsmethode hinzuzufügen. habe aber inzwischen gelernt, dass dies ohne eine instanziierte Instanz nicht möglich ist. Klingt so, als würden Sie sagen, dass das Hinzufügen einer Erweiterungsmethode eine Form der Überladung ist? Ich habe das nie in Betracht gezogen. Ist das richtig? jetzt wo ich darüber nachdenke ... was genau bedeutet Überladung?
Zach Smith
@ZachSmith Oh, ich dachte, Sie fügen eine Erweiterung namens "DateTime.MaxOf (dt1, dt2)" hinzu, genau wie "DateTime.Now", die auf statischen DateTime-Mitgliedern basiert.
Shtse8
-2

Nachdem wir LINQ haben, können Sie ein Array mit Ihren beiden Werten (DateTimes, TimeSpans usw.) erstellen und dann die Erweiterungsmethode .Max () verwenden.

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

Es liest sich gut, ist so effizient wie Max und kann für mehr als 2 Vergleichswerte wiederverwendet werden.

Das ganze Problem unten, sich Sorgen um .Kind zu machen, ist eine große Sache ... aber ich vermeide das, indem ich niemals in Ortszeiten arbeite. Wenn ich zeitlich etwas Wichtiges habe, arbeite ich immer in UTC, auch wenn es mehr Arbeit bedeutet, dorthin zu gelangen.

Craig Brunetti
quelle
1
Kopie meiner Antwort
Toshi
-3
// 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/

Sergey Suworow
quelle
Guter Vorschlag (wirklich), aber ohne Beschreibung ist es schwer zu finden, warum es gut ist. Bitte beschreiben Sie, wo der Trick ist. Ohne die Beschreibung ist es nur ein Codeblock und keine Antwort.
Artemix
3
Frage ist markiert .NET nicht Javascript
hawbsl
Entschuldigung, ich habe .NET nicht bemerkt. Auf jeden Fall können wir das Mindestdatum auf der Clientseite finden und an den Server senden.
Sergey Suworow
4
Sie gehen davon aus, dass es sich um Asp handelt, was nicht unbedingt richtig ist. Es wäre auch ziemlich dumm, den Unterschied auf dem Client zu berechnen, da es weitaus mehr Risiken gibt (JavaScript deaktiviert), unnötigen Datenverkehr erzeugt und (abhängig von der Netzwerkgeschwindigkeit) langsamer wäre
Jalgames