DateTime Porównaj, jak sprawdzić, czy data ma mniej niż 30 dni?

86

Próbuję dowiedzieć się, czy konto wygaśnie za mniej niż 30 dni. Czy prawidłowo używam porównania dat i godzin?

if (DateTime.Compare(expiryDate, now) < 30)

{
     matchFound = true;
}
David Basarab
źródło

Odpowiedzi:

232

Czy prawidłowo używam porównania dat i godzin?

Nie. CompareOferuje tylko informacje o względnym położeniu dwóch dat: mniej, równo lub więcej. To, czego chcesz, to coś takiego:

if ((expiryDate - DateTime.Now).TotalDays < 30)
    matchFound = true;

To odejmuje dwa DateTimes. Wynikiem jest TimeSpanobiekt, który ma TotalDayswłaściwość.

Dodatkowo warunek można zapisać bezpośrednio jako:

matchFound = (expiryDate - DateTime.Now).TotalDays < 30;

Nie ifpotrzeba.

Konrad Rudolph
źródło
2
Powinienem dać ci 2+;) jeden za odpowiedź i jeden za krótki sposób wyrażenia tego
CheGueVerra
4
Uh… właśnie przedłużyłem swoją odpowiedź, więc możesz odjąć jeden wyimaginowany głos. ;-)
Konrad Rudolph
1
Użyj TotalDayszamiast dni.
João Portela,
2
Jest koncepcyjnie dokładniejszy. Nie ma to znaczenia, ponieważ Daysjest największym składnikiem TimeSpan. Osoby czytające to mogą ekstrapolować to, sądząc, że Secondsnieruchomość działa w ten sam sposób.
João Portela,
2
Dodając do tego, co powiedział João Portela, nawet on Dayssam też może się mylić. Daysi TotalDayssą takie same tylko dlatego, że warunek jest < 30, ale byłaby oczywista różnica, gdyby tak było <= 30, ponieważ TotalDaysmoże zwrócić coś takiego 30.421, jak while Dayswciąż zwraca 30.
Racil Hilan
15

Powinien być

matchFound = (expiryDate - DateTime.Now).TotalDays < 30;

zanotuj całkowitą liczbę dni, w przeciwnym razie uzyskasz gorsze zachowanie

Łukasz
źródło
ta odpowiedź została udzielona ponad rok po ostatniej edycji zaakceptowanej odpowiedzi!
Mitch Wheat
@Mitch - To jest prawidłowa odpowiedź, zauważ, że używa TotalDays zamiast Days.
Marcelo Mason
Przyjęta odpowiedź jest prawidłowa. TotalDays zwraca również część ułamkową, która jest zbędna w porównaniu z liczbą całkowitą.
Mitch Wheat
1
@MitchWheat TotalDaysjest koncepcyjnie poprawnym polem do użycia. W praktyce dają ten sam wynik, ale tylko dlatego, że Daysjest to największy składnik TimeSpan, gdyby istniał składnik Miesiące lub Lata, a to byłaby inna historia. Tylko spróbuj Hours, Secondsalbo Millisecondszobaczyć, jak one działają.
João Portela,
7

Zamiast tego zrobiłbym to w ten sposób:

TimeSpan diff = expiryDate - DateTime.Today;
if (diff.Days > 30) 
   matchFound = true;

Porównaj odpowiada tylko liczbą całkowitą wskazującą, że pierwsza pogoda jest wcześniejsza, taka sama lub później ...

haqwin
źródło
6

Spróbuj tego zamiast tego

if ( (expiryDate - DateTime.Now ).TotalDays < 30 ) { 
  matchFound = true;
}
JaredPar
źródło
1
Hmm, musisz albo odwrócić kolejność dat, albo przyjąć wartość bezwzględną, chyba że data ważności już minęła.
Konrad Rudolph
3

Porównaj zwraca 1, 0, -1 dla odpowiednio większego niż, równego, mniejszego niż.

Chcesz:

    if (DateTime.Compare(expiryDate, DateTime.Now.AddDays(30)) <= 0) 
    { 
        bool matchFound = true;
    }
Mitch Wheat
źródło
1

To da ci dokładny wynik:

if ((expiryDate.Date - DateTime.Now.Date).Days < 30)
    matchFound = true;
Jayant
źródło
faktycznie to co się dzieje hr to np. expryDte to 28.04.2011, jeśli U rite (expiryDate-DateTime.now) to również zajmie trochę czasu (28.04.2011 12:00:00 - 26.04.2011 11 : 47: 00), a powyższy kod przyjmuje wartość 28/4/2011 12:00:00 AM -26/4/2011 12:00:00, co nie daje dokładnej różnicy.
Jayant
1

Porównanie jest niepotrzebne, dni / suma dni są niepotrzebne.

Wszystko czego potrzebujesz to

if (expireDate < DateTime.Now) {
    // has expired
} else {
    // not expired
}

pamiętaj, że zadziała, jeśli zdecydujesz się użyć minut, miesięcy lub nawet lat jako kryteriów wygaśnięcia.

obrabować
źródło
1
Niezbyt dobra odpowiedź, ponieważ teraz bierzesz pod uwagę godziny, minuty i sekundy. Data i godzina Dzisiejszy dzień byłby bardziej odpowiedni dla sytuacji PO.
JL.
1

Zakładając, że chcesz przypisać false(jeśli ma to zastosowanie) do matchtime, prostszy sposób zapisu byłby ...

matchtime = ((expiryDate - DateTime.Now).TotalDays < 30);
Magic Mick
źródło
Operator trójargumentowy jest tutaj całkowicie zbędny, ponieważ ((expiryDate - DateTime.Now) .TotalDays <30) już zwraca wartość logiczną.
Fabio
@Fabio Dzięki znajomemu usunęli je, aby przypisać wartość logiczną za pośrednictwem zwracanego typu.
Magic Mick
0

Nie, funkcja Porównaj zwróci wartość 1, 0 lub -1. 0 gdy te dwie wartości są równe, -1 i 1 oznaczają mniej niż i więcej niż, wierzę w tej kolejności, ale często mylę je.

Timothy Carter
źródło
0

Nie, nie używasz go poprawnie.

Zobacz tutaj po szczegóły.

DateTime t1 = new DateTime(100);
DateTime t2 = new DateTime(20);

if (DateTime.Compare(t1, t2) >  0) Console.WriteLine("t1 > t2"); 
if (DateTime.Compare(t1, t2) == 0) Console.WriteLine("t1 == t2"); 
if (DateTime.Compare(t1, t2) <  0) Console.WriteLine("t1 < t2");
David Basarab
źródło
0

To, co chcesz zrobić, to odjąć dwa DateTimes (expiryDate i DateTime.Now). To zwróci obiekt typu TimeSpan. TimeSpan ma właściwość „Days”. Dla swojej odpowiedzi porównaj tę liczbę z 30.

GWLlosa
źródło
0

Nie, to nie jest poprawne, spróbuj tego:

DateTime expiryDate = DateTime.Now.AddDays(-31);
if (DateTime.Compare(expiryDate, DateTime.Now.AddDays(-30)) < 1)
{
    matchFound = true;
}
Canavar
źródło
0

Właściwie żadna z tych odpowiedzi nie zadziałała dla mnie. Rozwiązałem to w ten sposób:

  if ((expireDate.Date - DateTime.Now).Days > -30)
  {
    matchFound = true;
  }

Kiedy próbowałem to zrobić:

matchFound = (expiryDate - DateTime.Now).Days < 30;

Dzisiaj, 2011-11-14, a moja data ważności to 2011-10-17, otrzymałem to matchFound = -28. Zamiast 28. Więc odwróciłem ostatni czek.

SBergstrom
źródło
0
// this isn't set up for good processing.  
//I don't know what data set has the expiration 
//dates of your accounts.  I assume a list.
// matchfound is a single variablethat returns true if any 1 record is expired.

bool matchFound = false;
            DateTime dateOfExpiration = DateTime.Today.AddDays(-30);
            List<DateTime> accountExpireDates = new List<DateTime>();
            foreach (DateTime date in accountExpireDates)
            {
                if (DateTime.Compare(dateOfExpiration, date) != -1)
                {
                    matchFound = true;
            }
            }
Alex
źródło
1
Czy to nie jest trochę skomplikowane?
Max
Gdzie w pytaniu jest wzmianka o datach ważności konta? Skopiowałeś wklejone złe rozwiązanie. matchFound brzmi prawie tak, jakbyś miksował Pattern lub RegEx. Przy okazji, musisz przerwać, gdy zostanie znalezione dopasowanie lub kontynuuje zapętlenie. A jeśli to jest -2? MSDN nie podaje, że możliwe wartości to -1, 0 i 1.
Mukus,
0

Możesz spróbować zrobić tak:

var daysPassed = (DateTime.UtcNow - expiryDate).Days;
if (daysPassed > 30)
{ 
    // ...
}
vlad
źródło
6
Postaraj się, aby Twoje wyjaśnienie było bardziej opisowe.
borchvm