2009-12-31 10 views
258

Jaki jest najszybszy i najłatwiejszy sposób uzyskania wartości Min (lub Max) między dwiema datami? Czy istnieje odpowiednik Math.Min (& Math.Max) dla dat?Równoważnik Math.Min & Math.Max ​​for Dates?

chcę zrobić coś takiego:

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

Oczywiście powyższe Math.min nie działa, ponieważ są one dat.

Odpowiedz

277

Nie ma przeciążenia dla wartości DateTime, ale można uzyskać długą wartość Ticks to, co zawierają wartości, porównaj je, a następnie utworzyć nowy wartość DateTime z wyniku.

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

(Należy pamiętać, że struktura DateTime zawiera również właściwość Kind, które nie są przechowywane w nową wartość ta nie jest zwykle problemem, jeśli porównać wartości DateTime różnego rodzaju compa Rison nie ma sensu i tak.)

+2

wydawało mi się to najbliższe jednoliniowemu zamiennikowi/odpowiednikowi dla Math.Min, ale inne odpowiedzi też były świetne, dla kompletności – hawbsl

+3

-, całkowicie tracisz wszystkie informacje (z wyjątkiem tyknięć) oryginalnego 'System.DateTime' -instance –

+1

@AndreasNiedermair: Jedyne informacje, które istnieją w wartości 'DateTime', to własności' Ticks' i 'Kind'. Wszystkie pozostałe właściwości pochodzą od nich. – Guffa

324

Nie ma wbudowanej metody, aby to zrobić. Możesz użyć wyrażenia:

(date1 > date2 ? date1 : date2) 

, aby znaleźć maksimum dwóch.

Można napisać rodzajowego metody obliczania Min lub Max dla każdego typu (pod warunkiem, że Comparer<T>.Default jest ustawiona odpowiednio):

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

Można użyć LINQ też:

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

Jak o:

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

Działa z każdą opcją pe, który obsługuje IComparable<T> lub IComparable.

Właściwie z LINQ, inną alternatywą jest:

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

głosów się na przykład LINQ. –

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

+0

Dobra sugestia (naprawdę), ale bez opisu trudno jest znaleźć powód, dla którego jest dobra. Opisz, gdzie jest sztuczka. Bez opisu to tylko blok kodu, a nie odpowiedź. – Artemix

+2

pytanie jest oznaczone .NET nie Javascript – hawbsl

+0

Niestety, nie zauważyłem .NET. W każdym razie, możemy znaleźć termin min na stronie klienta i wysłać go na serwer. –

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

Pozwala to terminy mają różne „rodzaje” i zwraca instancję, która została uchwalona w (nie wraca nowy DateTime wykonaną z Kleszcze lub milisekundy).

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

Zauważ, że ten test nie powiedzie się na wschód od Greenwich ...

6

Jeśli chcesz to nazwać raczej Math.Max, można zrobić coś takiego bardzo krótkim korpusie wyrażenie:

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

oh, to geniusz! W ten sposób nie muszę porównywać się za każdym razem, tylko raz po tym, jak skończę dane. Dziękuję Ci bardzo! – tfrascaroli

3

Linq.Min()/Linq.Max() podejście:

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

Teraz, gdy mamy LINQ, można utworzyć tablicę ze swoimi dwoma wartościami (DateTimes, TimeSpans, cokolwiek), a następnie użyj metody rozszerzenia .Max().

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

Brzmi ładnie, jest tak wydajny, jak może być Max, i nadaje się do wielokrotnego użytku dla więcej niż 2 wartości porównania.

Cały problem poniżej, martwienie się o .Kind to wielka sprawa ... ale unikam tego, nigdy nie pracując w lokalnych czasach, nigdy. Jeśli mam coś ważnego w odniesieniu do czasów, zawsze pracuję w UTC, nawet jeśli oznacza to więcej pracy.

0

Co powiesz na metodę rozszerzenia DateTime?

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

Zastosowanie:

var maxDate = date1.MaxOf(date2);