Équivalent de Math.Min & Math.Max ​​pour les dates?

Quel est le moyen le plus rapide et le plus simple d’obtenir la valeur Min (ou Max) entre deux dates? Y a-t-il un équivalent à Math.Min (& Math.Max) pour les dates?

Je veux faire quelque chose comme:

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

Évidemment, le Math.Min ci-dessus ne fonctionne pas parce que ce sont des dates.

Il n’y a pas de surcharge pour les valeurs DateTime, mais vous pouvez obtenir la valeur longue Ticks qui correspond aux valeurs, les comparer et créer une nouvelle valeur DateTime à partir du résultat:

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

(Notez que la structure DateTime contient également une propriété Kind , qui n’est pas conservée dans la nouvelle valeur. Ce n’est normalement pas un problème; si vous comparez des valeurs DateTime de différents types, la comparaison n’a aucun sens de toute façon.)

Il n’y a pas de méthode intégrée pour faire cela. Vous pouvez utiliser l’expression:

 (date1 > date2 ? date1 : date2) 

trouver le maximum des deux.

Vous pouvez écrire une méthode générique pour calculer Min ou Max pour tout type (à condition que Comparer.Default soit défini correctement):

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

Vous pouvez aussi utiliser LINQ:

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

Que diriez-vous:

 public static T Min(params T[] values) { if (values == null) throw new ArgumentNullException("values"); var comparer = Comparer.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 x, T y) { return Comparer.Default.Compare(x, y) < 0 ? x : y; } 

Fonctionne avec tout type IComparable charge IComparable ou IComparable .

En fait, avec LINQ, une autre alternative est:

 var min = new[] {x,y,z}.Min(); 
 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; } } 

Cela permet aux dates d’avoir différents types et renvoie l’instance qui a été transmise (sans renvoyer un nouveau DateTime construit à partir de Ticks ou Milliseconds).

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

Notez que ce test échouerait à l’est de Greenwich …

Si vous voulez l’appeler plus comme Math.Max, vous pouvez faire quelque chose comme ce corps d’expression très court:

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

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

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

Maintenant que nous avons LINQ, vous pouvez créer un tableau avec vos deux valeurs (DateTimes, TimeSpans, peu importe), puis utiliser la méthode d’extension .Max ().

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

Il lit bien, il est aussi efficace que Max peut l’être et il est réutilisable pour plus de 2 valeurs de comparaison.

Tout le problème ci-dessous est préoccupant pour .Kind est un gros problème … mais j’évite cela en ne travaillant jamais à l’heure locale, jamais. Si j’ai quelque chose d’important concernant les temps, je travaille toujours en UTC, même si cela signifie plus de travail pour y arriver.

Que diriez-vous d’une méthode d’extension DateTime ?

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

Usage:

 var maxDate = date1.MaxOf(date2); 
 // 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/