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

369

Quelle est la manière la plus rapide et la plus simple d'obtenir la valeur Min (ou Max) entre deux dates? Existe-t-il un équivalent de 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, Math.Min ci-dessus ne fonctionne pas car ce sont des dates.

hawbsl
la source

Réponses:

416

Il n'y a pas de surcharge pour les valeurs DateTime, mais vous pouvez obtenir la valeur longue Ticksqui est ce que les valeurs contiennent, les comparer, puis 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 Kindpropriété 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 de toute façon aucun sens.)

Guffa
la source
2
cela me semblait être le plus proche d'un remplacement / équivalent d'une ligne pour Math.Min mais les autres réponses étaient également très bien, pour être complet
hawbsl
6
-, vous System.DateTimeperdez complètement toutes les informations (sauf les tiques) de l' instance originale
Andreas Niedermair
9
@AndreasNiedermair: Si vous comparez des dates de différents types, vous ne pouvez pas simplement les comparer de toute façon. J'ai déjà couvert cela dans la réponse.
Guffa
4
@Iain: Vous pouvez toujours les comparer, mais si vous comparez des valeurs qui ne sont pas comparables, le résultat est inutile. C'est la même chose qu'avec toute autre valeur qui n'est pas comparable, comme comparer une distance en kilomètres avec une distance en miles; vous pouvez comparer les valeurs très bien, mais cela ne veut rien dire.
Guffa
4
-1 pour avoir fait la main sur Kind. Comme indiqué dans la réponse de @ user450, il est assez facile de convertir les deux fois en UTC et de les comparer en toute sécurité sans jeter d'informations.
piedar
484

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

(date1 > date2 ? date1 : date2)

pour trouver le maximum des deux.

Vous pouvez écrire une méthode générique pour calculer Minou Maxpour tout type (à condition qu'elle Comparer<T>.Defaultsoit définie de manière appropriée):

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

Vous pouvez également utiliser LINQ:

new[]{date1, date2, date3}.Max()
Mehrdad Afshari
la source
15
C'EST en fait la réponse qui mérite d'être acceptée.
Larry
38

Que diriez-vous:

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

Fonctionne avec tout type qui prend en charge IComparable<T>ou IComparable.

En fait, avec LINQ, une autre alternative est:

var min = new[] {x,y,z}.Min();
Marc Gravell
la source
6
Votez pour l'exemple LINQ.
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;
    }
}

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 de millisecondes).

[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 ...

user450
la source
Pourquoi ne pas simplement supprimer la partie ToUniversalTime ()?
David Thielen,
18

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

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);
R. Salisbury
la source
oh, c'est du génie! De cette façon, je n'ai pas à comparer chaque fois, juste une fois après avoir fini avec les données. Merci beaucoup!
tfrascaroli
Ceci est une solution très élégante
pberggreen
2

Que diriez-vous d'une DateTimeméthode d'extension?

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

Usage:

var maxDate = date1.MaxOf(date2);
Oundless
la source
Je préférerais l'utiliser comme ça DateTime.MaxOf(dt1, dt2), mais je ne sais pas comment faire ça ...
Zach Smith
@ZachSmith Vous ne pouvez pas surcharger la classe DateTime car elle n'est pas partielle. Peut-être que nous pouvons utiliser DateTimeHelper.Max (dt1, dt2)
shtse8
@ shtse8 - que voulez-vous dire par surcharge? je pensais ajouter une méthode d'extension. mais ont depuis appris que cela ne peut se faire sans une instance instanciée. sonne comme vous dites que l'ajout d'une méthode d'extension est une forme de surcharge? je n'y ai jamais pensé .. est-ce exact? maintenant que j'y pense ... qu'est-ce que la surcharge signifie exactement?
Zach Smith
@ZachSmith Oh, je pensais que vous ajoutez une extension appelée "DateTime.MaxOf (dt1, dt2)" tout comme "DateTime.Now" qui est basé sur les membres statiques DateTime.
shtse8
-2

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 se lit bien, il est aussi efficace que Max et peut être réutilisé pour plus de 2 valeurs de comparaison.

Tout le problème ci-dessous est inquiétant 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 horaires, je travaille toujours à l'UTC, même si cela signifie plus de travail pour y arriver.

Craig Brunetti
la source
1
copie de ma réponse
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 Suvorov
la source
Bonne suggestion (vraiment), mais sans description, il est difficile de trouver pourquoi elle est bonne. Veuillez décrire où se trouve l'astuce. Sans la description, ce n'est qu'un bloc de code et non une réponse.
Artemix
3
question est étiquetée .NET pas Javascript
hawbsl
Désolé, je n'ai pas remarqué .NET. Quoi qu'il en soit, nous pouvons trouver la date min du côté client et l'envoyer au serveur.
Sergey Suvorov
4
Vous supposez que nous parlons d'asp, ce qui n'est pas nécessairement juste. Il serait également assez stupide de calculer la différence sur le client, car il y a beaucoup plus de risques (JavaScript désactivé), cela générerait du trafic inutile et ce serait (selon la vitesse du réseau) plus lent
jalgames