Tarihler için Math.Min ve Math.Max ​​eşdeğeridir?


369

İki tarih arasında Min (veya Maks) değerini almanın en hızlı ve en kolay yolu nedir? Tarihler için Math.Min (& Math.Max) eşdeğeri var mı?

Gibi bir şey yapmak istiyorum:

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

Açıkçası yukarıdaki Math.Min çalışmıyor çünkü tarihler.

Yanıtlar:


416

DateTime değerleri için aşırı yük yoktur, ancak Ticksdeğerlerin içerdiği uzun değeri alabilir , karşılaştırabilir ve sonuçtan yeni bir DateTime değeri oluşturabilirsiniz:

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

(DateTime yapısının da Kindyeni değerde tutulmayan bir özellik içerdiğini unutmayın . Bu normalde bir sorun değildir; Farklı türde DateTime değerlerini karşılaştırırsanız karşılaştırma yine de mantıklı değildir.)


2
bu bana Math.Min için bir satır değiştirme / eşdeğeri en yakın gibi görünüyordu ama diğer cevaplar da
tamlık

6
-, orijinalin tüm bilgilerini (keneler hariç) tamamen kaybedersiniz System.DateTime-Anlama
Andreas Niedermair

9
@AndreasNiedermair: Farklı türdeki tarihleri ​​karşılaştırıyorsanız, bunları doğrudan karşılaştıramazsınız. Bunu zaten cevapta ele aldım.
Guffa

4
@Iain: Her zaman olabilir bunları karşılaştırmak, ancak karşılaştırılabilir değildir değerleri karşılaştırmak ise, sonuç işe yaramaz. Bu, karşılaştırılamayan diğer değerlerle aynıdır, örneğin kilometre cinsinden bir mesafeyi mil cinsinden bir mesafeyle karşılaştırmak gibi; değerleri gayet iyi bir şekilde karşılaştırabilirsiniz, ancak hiçbir şey ifade etmez.
Guffa

4
Tür hakkında el yıkama için -1. @ User450'nin cevabında gösterildiği gibi, her iki zamanı UTC'ye dönüştürmek ve bilgi atmadan güvenli bir şekilde karşılaştırmak oldukça kolaydır.
Pie

484

Bunu yapmak için yerleşik bir yöntem yoktur. Şu ifadeyi kullanabilirsiniz:

(date1 > date2 ? date1 : date2)

ikisinin maksimumunu bulmak için.

Hesaplamak için Minveya Maxherhangi bir tür için ( Comparer<T>.Defaultuygun şekilde ayarlanması koşuluyla) genel bir yöntem yazabilirsiniz :

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

LINQ'yu da kullanabilirsiniz:

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

15
BU aslında kabul edilmeyi hak eden cevaptır.
Larry

38

Nasıl olur:

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

IComparable<T>Veya özelliğini destekleyen herhangi bir türle çalışır IComparable.

Aslında, LINQ ile başka bir alternatif:

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

6
LINQ örneği için oy verin.
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;
    }
}

Bu, tarihlerin farklı 'türlere' sahip olmasını sağlar ve iletilen örneği döndürür (Keneler veya Milisaniyelerden oluşturulmuş yeni bir DateTime döndürmez).

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

Bu testin Greenwich'in doğusunda başarısız olacağını unutmayın ...


Neden sadece ToUniversalTime () bölümünü bırakmıyorsunuz?
David Thielen

18

Linq.Min()/ Linq.Max()yaklaşım:

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

Daha çok Math.Max ​​gibi aramak istiyorsanız, bu çok kısa ifade gövdesi gibi bir şey yapabilirsiniz:

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

oh, bu dahi! Bu şekilde her seferinde karşılaştırma yapmak zorunda değilim, verilerle işimi bitirdikten sadece bir kez sonra. Çok teşekkür ederim!
tfrascaroli

Bu çok zarif bir çözüm
pberggreen

2

Bir DateTimeuzantı yöntemine ne dersiniz ?

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

Kullanımı:

var maxDate = date1.MaxOf(date2);

Bunu kullanmayı tercih ederim DateTime.MaxOf(dt1, dt2), ama bunu nasıl yapacağımı bilmiyorum ...
Zach Smith

@ZachSmith DateTime sınıfını kısmi olmadığı için aşırı yükleyemezsiniz. Belki DateTimeHelper.Max (dt1, dt2) kullanabiliriz
shtse8

@ shtse8 - aşırı yükleme ile ne demek istiyorsun? bir eklenti yöntemi eklemeyi düşünüyordum. ama o zamandan beri bunun somut bir örnek olmadan yapılamayacağını öğrendiler. Bir uzantı yöntemi eklemenin aşırı yüklenmenin bir yolu olduğunu mu söylüyorsunuz? bunu hiç düşünmemiştim .. bu doğru mu? şimdi düşündüğüme göre ... aşırı yükleme tam olarak ne anlama geliyor?
Zach Smith

@ZachSmith Oh, tıpkı DateTime statik üyelerine dayanan "DateTime.Now" gibi "DateTime.MaxOf (dt1, dt2)" adlı bir uzantı eklediğinizi düşündüm.
shtse8

-2

Artık LINQ'muz olduğuna göre, iki değerinizle (DateTimes, TimeSpans, ne olursa olsun) bir dizi oluşturabilir ve sonra .Max () uzantı yöntemini kullanabilirsiniz.

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

Güzel okuyor, Max olabildiğince verimli ve 2'den fazla karşılaştırma değeri için tekrar kullanılabilir.

Aşağıdaki sorun .Kind hakkında endişelenmek büyük bir anlaşma ... ama ben asla yerel zamanlarda, hiç çalışarak bunu önlemek. Zamanlarla ilgili önemli bir şeyim varsa, oraya gitmek için daha fazla iş anlamına gelse bile her zaman UTC'de çalışıyorum.


1
cevabımın kopyası
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/


İyi öneri (gerçekten), ancak açıklama olmadan neden iyi olduğunu bulmak zor. Lütfen hilenin nerede olduğunu açıklayın. Açıklama olmadan bu sadece bir kod bloğudur ve bir cevap değildir.
Artemix

3
sorusu etiketli bir .NET değil JavaScript olduğunu
hawbsl

Üzgünüm, .NET fark etmedi. Her neyse, istemci tarafında min tarihini bulabilir ve sunucuya gönderebiliriz.
Sergey Suvorov

4
Mutlaka doğru olmayan asp hakkında konuştuğumuzu varsayıyorsunuz. Ayrıca, İstemcideki farkı hesaplamak oldukça aptalca olurdu, çünkü çok daha fazla risk var (JavaScript devre dışı), gereksiz trafik üretecek ve (ağ hızına bağlı olarak) daha yavaş olacaktır
jalgames
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.