Equivalente a Math.Min & Math.Max ​​para fechas?


369

¿Cuál es la forma más rápida y fácil de obtener el valor Min (o Max) entre dos fechas? ¿Hay un equivalente a Math.Min (& Math.Max) para las fechas?

Quiero hacer algo como:

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

Obviamente, el Math.Min anterior no funciona porque son fechas.

Respuestas:


416

No hay sobrecarga para los valores de DateTime, pero puede obtener el valor largo Ticksque es lo que contienen los valores, compararlos y luego crear un nuevo valor de DateTime a partir del resultado:

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

(Tenga en cuenta que la estructura DateTime también contiene una Kindpropiedad, que no se retiene en el nuevo valor. Esto normalmente no es un problema; si compara los valores DateTime de diferentes tipos, la comparación no tiene sentido de todos modos).


2
esto me pareció más cercano a un reemplazo / equivalente de una línea para Math.Min pero las otras respuestas también fueron geniales, para completar
hawbsl

66
-, pierde completamente toda la información (excepto los ticks) de la System.DateTimeinstancia original
Andreas Niedermair

99
@AndreasNiedermair: Si está comparando fechas de diferentes tipos, no puede compararlas directamente de todos modos. Ya cubrí esto en la respuesta.
Guffa

44
@Iain: Siempre puedes compararlos, pero si comparas valores que no son comparables, el resultado es inútil. Es igual que con cualquier otro valor que no sea comparable, como comparar una distancia en kilómetros con una distancia en millas; puedes comparar los valores bien, pero no significa nada.
Guffa

44
-1 para saludar a mano sobre Kind. Como se muestra en la respuesta de @ user450, es bastante fácil convertir ambas veces a UTC y compararlas de forma segura sin descartar información.
piedar

484

No hay un método integrado para hacer eso. Puedes usar la expresión:

(date1 > date2 ? date1 : date2)

para encontrar el máximo de los dos.

Puede escribir un método genérico para calcular Mino Maxpara cualquier tipo (siempre que Comparer<T>.Defaultesté configurado correctamente):

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

También puedes usar LINQ:

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

15
ESTA es realmente la respuesta que merece ser aceptada.
Larry

38

Qué tal si:

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

Funciona con cualquier tipo que soporte IComparable<T>o IComparable.

En realidad, con LINQ, otra alternativa es:

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

66
Vote por el ejemplo de LINQ.
Infinito

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

Esto permite que las fechas tengan diferentes 'tipos' y devuelve la instancia que se pasó (sin devolver un nuevo DateTime construido a partir de Ticks o Milisegundos).

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

Tenga en cuenta que esta prueba fallaría al este de Greenwich ...


¿Por qué no simplemente soltar la parte ToUniversalTime ()?
David Thielen

18

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

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

17

Si desea llamarlo más como Math.Max, puede hacer algo como este cuerpo de expresión muy breve:

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

oh, eso es genial! De esta manera, no tengo que comparar cada vez, solo una vez después de haber terminado con los datos. ¡Muchas gracias!
tfrascaroli

Esta es una solución muy elegante
pberggreen

2

¿Qué tal un DateTimemétodo de extensión?

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

Uso:

var maxDate = date1.MaxOf(date2);

Preferiría usarlo como DateTime.MaxOf(dt1, dt2), pero no sé cómo hacerlo ...
Zach Smith

@ZachSmith No puede sobrecargar la clase DateTime porque no es parcial. Tal vez podamos usar DateTimeHelper.Max (dt1, dt2)
shtse8

@ shtse8: ¿qué quiere decir con sobrecarga? Estaba pensando en agregar un método de extensión. pero desde entonces he aprendido que no se puede hacer sin una instancia instanciada. ¿Parece que estás diciendo que agregar un método de extensión es una forma de sobrecarga? Nunca he considerado eso ... ¿es correcto? ahora que lo pienso ... ¿qué significa exactamente sobrecargar?
Zach Smith

@ZachSmith Oh, pensé que estaba agregando una extensión llamada "DateTime.MaxOf (dt1, dt2)" al igual que "DateTime.Now" que se basa en miembros estáticos DateTime.
shtse8

-2

Ahora que tenemos LINQ, puede crear una matriz con sus dos valores (DateTimes, TimeSpans, lo que sea) y luego usar el método de extensión .Max ().

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

Se lee bien, es tan eficiente como Max puede ser, y es reutilizable para más de 2 valores de comparación.

Todo el problema a continuación preocuparse por .Kind es un gran problema ... pero lo evito al nunca trabajar en horarios locales, nunca. Si tengo algo importante con respecto a los tiempos, siempre trabajo en UTC, incluso si eso significa más trabajo para llegar allí.


1
copia de mi respuesta
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/


Buena sugerencia (realmente), pero sin descripción es difícil encontrar por qué es buena. Describe dónde está el truco. Sin la descripción es solo un bloque de código y no una respuesta.
Artemix

3
pregunta está etiquetada .NET no Javascript
hawbsl

Lo sentimos, no noté .NET. De todos modos, podemos encontrar la fecha mínima en el lado del cliente y enviarla al servidor.
Sergey Suvorov

44
Asumes que estamos hablando de asp, que no es necesariamente correcto. También sería bastante estúpido calcular la diferencia en el Cliente, porque hay muchos más riesgos (JavaScript deshabilitado), generaría tráfico innecesario y sería (dependiendo de la velocidad de la red) más lento
jalgames
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.