2013-06-05 13 views
7

Próbuję uzyskać alert, gdy klient ma urodziny w ciągu najbliższych 7 dni.Porównaj DateTime bez roku

Próbowałem go z tym kodem:

public bool IsBirthdayImminent 
{ 
    get { return DateOfBirth != null && DateOfBirth.Value.Date >= DateTime.Today.Date.AddDays(-7); } 
} 

Oczywiście to nie zadziała, a data jest przechowywana z jej roku (słownie 05/21/1980) i porównuje również rok . Więc to zapytanie nigdy nie będzie true - cóż, nie, jeśli urodziłeś się w ciągu następnych siedmiu dni.

Jak zmienić to zapytanie, aby zignorować rok?

Edit:

porządku, sama kwerenda nie jest w ogóle problem. Moim głównym celem jest radzenie sobie z latami przestępnymi i sytuacjami około grudnia < -> stycznia.

+0

Spróbuj: DateOfBirth.Value.Date> = DateTime.Today.Date.AddYears (DateOfBirth.Value.Date.Year - DateTime.Today.Date.Year) .AddDays (-7) – NeverHopeless

+0

Normalizuj obie daty: utwórz kopię wartości DOB i ustawić rok na taki sam jak rok bieżący. Teraz będziesz porównywać jabłka z jabłkami. – Icarus

+0

@Idle_Mind Może to nie mieć problemów z latami przestępnymi? Jeśli na przykład jedna z dat to 29 lutego 1996 r., A Ty spróbujesz ustawić ją na 29 lutego 2013 r., Możesz nie uzyskać pożądanego rezultatu. To samo dotyczy wszelkich innych różnic między datami na przestrzeni lat. – Servy

Odpowiedz

8

Proponuję użyć następującego kodu. Dotyczy to spraw w okresie od grudnia do stycznia oraz w dniu 29 lutego. Chociaż możesz chcieć zobaczyć i poprawić 28 lutego, aby zostać uwzględnionym lub wykluczonym w ramach danego days.

BirthdayImminent(new DateTime(1980, 1, 1), new DateTime(2012, 1, 2), 7); // false 
    BirthdayImminent(new DateTime(1980, 1, 1), new DateTime(2012, 12, 28), 7); // true 
    BirthdayImminent(new DateTime(1980, 2, 28), new DateTime(2012, 2, 21), 7); // true 

    private static bool BirthdayImminent(DateTime birthDate, DateTime referenceDate, int days) 
    { 
     DateTime birthdayThisYear = birthDate.AddYears(referenceDate.Year - birthDate.Year); 

     if (birthdayThisYear < referenceDate) 
      birthdayThisYear = birthdayThisYear.AddYears(1); 

     bool birthdayImminent = (birthdayThisYear - referenceDate).TotalDays <= days; 

     return birthdayImminent; 
    } 

Pamiętaj również o przypadku krawędzi Guvante opublikowanym w komentarzach poniżej.

+0

+1 dla 'AddYears' zamiast próby zhakowania razem konstruktora. Technicznie dla 'dni> = 60' liczba dni, w które obchodzisz urodziny, wynosi jeden. Usunięcie funkcji 'AddYears' z' birthDate' naprawiłoby ten warunek brzegowy ('2/29/2012.AddYears (3) .AddYears (1) == 2/28/2016'). Jednak biorąc pod uwagę wymagania, powiedziałbym, że twoja metoda jest najlepsza, ponieważ korekta dodaje nie uzasadnioną redundancję. – Guvante

+1

@Guvante To nie dotyczy wszystkich dni> = 60, tylko lata przestępne, gdy bieżąca data jest także rokiem przestępnym, ale przed 28 dniem. W takich warunkach jest jednak wyłączony o jeden dzień. Dlatego tak rzadko odpowiadam na pytania typu DateTime. Są super nieuporządkowane. – Servy

+0

@Servy: Czy uważasz, że poprawienie liczby dni przestępnych pomiędzy 'birthdayThisYear' (po ostatnim przypisaniu) i' birthDate' będzie wystarczające? – Caramiriel

0

Ustaw rok BRUDDATE jawnie na DateTime.Today.Year, a będzie porównywać dobrze.

+1

Należy jednak pamiętać o przypadkach w grudniu i styczniu. – Caramiriel

1

coś takiego:

DateTime birthDate = new DateTime(2012, 12, 2); 

DateTime birthdayThisYear; 
if (birthDate.Month == 2 && birthDate.Day == 29 && DateTime.IsLeapYear(DateTime.Now.Year)) 
    birthdayThisYear = new DateTime(DateTime.Now.Year, 2, 28); 
else 
    birthdayThisYear = new DateTime(DateTime.Now.Year, birthDate.Month, birthDate.Day); 

bool birthdayImminent = birthdayThisYear > DateTime.Now && (birthdayThisYear - DateTime.Now).TotalDays <= 7; 

Jako getter:

public bool IsBirthdayImminent 
{ 
    get 
    { 
     if (DateOfBirth == null) 
      return false; 
     else 
     { 
      DateTime birthdayThisYear; 
      if (birthDate.Month == 2 && birthDate.Day == 29 && DateTime.IsLeapYear(DateTime.Now.Year)) 
       birthdayThisYear = new DateTime(DateTime.Now.Year, 2, 28); 
      else 
       birthdayThisYear = new DateTime(DateTime.Now.Year, birthDate.Month, birthDate.Day); 

      return birthdayThisYear > DateTime.Now && (birthdayThisYear - DateTime.Now).TotalDays <= 7; 
     } 
    } 
} 
+2

-1 Jeśli ktoś urodził się 29 lutego, to wyrzuci wyjątek za większość lat, gdy go nazwiesz. – Servy

+0

@SeToY - Wygląda dobrze. Warto również dodać czek, aby upewnić się, że bithdate jest w przyszłości, tj. "&& birthdayThisYear> DateTime.Now" – MarcF

+0

@Servy - Dobre miejsce, to wymagałoby sprawdzenia dla urodzin, gdzie miesiąc to "luty", a Day to " 29. ", gdzie PO musi zdecydować, jak obsługiwać dzień -1. – MarcF

-1

Spróbuj tego:

public bool IsBirthdayImminent 
{ 
    get { return DateOfBirth != null && DateOfBirth.Value.Date.AddYear(DateTime.Now.Year -DateOfBirth.Value.Year) >= DateTime.Today.Date.AddDays(-7); } 
} 
+0

To się zwróci, jeśli urodziny były albo w ciągu ostatnich 7 dni, albo w dowolnym momencie od teraz do końca roku. – yoozer8

+0

To nie jest zbyt eleganckie, a są lepsze rozwiązania! i zgadzam się z @ Jim – Mehran

0

Można użyć "DAYOFYEAR":

public bool IsBirthdayImminent 
{ 
    get { return DateOfBirth != null && Math.Abs(DateOfBirth.Value.Date.DayOfYear - DateTime.Today.DayOfYear) <= 7; } 
} 
+3

Jak to działa lat przestępnych? Jeśli twoje urodziny są w roku przestępnym, a po dniu 29 lutego, dzień roku jest o jeden dłuższy niż ten rok w roku innym niż przestępny, czyż nie? – Servy

+0

Hm, dobry punkt. DayOfYear po prostu zwraca wartość całkowitą z zakresu od 1 do 366, więc masz rację; to zepsułoby twoje wyniki. – bbar

+0

@Servy Jeśli jest 29 lutego pomiędzy 'DateofBirth.Value.Date' i' DateTime.Today', to wartość z tego odejmowania będzie o 1 mniejsza niż powinna być. Jeśli są dwa lub więcej, nadal będzie wyłączony o 1 dzień. –

Powiązane problemy