2009-06-11 10 views
14

Zastanawiasz się, czy znasz jakieś eleganckie rozwiązanie dla poniższych.Obliczenia na koniec miesiąca

Jeśli mam 30 czerwca 2009 roku i dodam miesiąc chcę iść do 31 lipca 2009 roku, a nie 30 lipca 2009 r

Ta logika opiera się na fakcie, że 30 czerwca 2009 roku był koniec miesiąca czerwca i kiedy dodaję miesiąc, chcę iść do końca następnego miesiąca.

Ale jeśli mam 29 czerwca 2009 roku oraz dodam miesiąc należy przejść do 29 lipca 2009.

Uwaga muszę być w stanie dodać dowolną liczbę miesięcy i muszę brać pod konto lat przestępnych.

Wiem również, że logika jest wątpliwa, ale jest to wymóg biznesowy, który działa z umowami na koniec miesiąca, które będą realizowane do końca miesiąca przez miesiąc w przyszłości.

Myślałem o kilku rozwiązaniach, ale nie są one bardzo eleganckie. Dlatego myślałem, że ktoś może mieć lepszy sposób.

Cheers Anthony

+1

Sprzeciwiasz się sobie. "Jeśli mam 30 czerwca 2009 r. I dodaję miesiąc, nie chcę, aby trafił do 31 lipca 2009 r. ... kiedy dodam miesiąc, chcę iść do końca następnego miesiąca.". Czy chcesz powiedzieć, że chcesz jechać do końca miesiąca? –

+0

Właśnie zauważyłem, że ja sam ... :) –

+0

Jakie są twoje nieeleganckie rozwiązania? –

Odpowiedz

32

Aby sprawdzić, czy data jest koniec miesiąca, sprawdzić, czy następnego dnia jest dzień jednym z jakiegoś miesiąca. twój algorytm powinien wtedy być "Jeśli dzień nie jest koniec miesiąca, dodać 1 miesiąc. Jeśli jest koniec miesiąca, dodać jeden dzień, dodać jeden miesiąc, odjąć jeden dzień."

bool IsEndOfMonth(DateTime date) { 
     return date.AddDays(1).Day == 1; 
    } 
    DateTime AddMonthSpecial(DateTime date) { 
     if (IsEndOfMonth(date)) 
      return date.AddDays(1).AddMonths(1).AddDays(-1); 
     else 
      return date.AddMonths(1); 
    } 
+0

Co z 31 grudnia 2009 + 2 miesiące. Powinien być 28 lutego 2010 ... –

+0

Przepraszam, popełniłem błąd w wyjaśnieniu "dodaj jeden dzień, dodaj miesiąc, odejmij jeden miesiąc" powinno być "dodaj dzień, dodaj miesiąc, odejmij dzień". Naprawiłem to ostatnie zdanie. – Jimmy

+1

Twój przykład nadal działa, ponieważ dodajesz 2 miesiące do 1 stycznia 2010 r., Uzyskując 1 marca 2010 r., A następnie odejmując 1 dzień, aby uzyskać "1 dzień przed następnym miesiącem", co jest równoznaczne z "ostatnim dniem miesiąca" – Jimmy

1

Czy możesz tam dotrzeć, zaczynając od pierwszego dnia poprzedniego miesiąca i cofając się o jeden dzień?

0
  1. Sprawdź, czy stara data to "koniec miesiąca".
    1. Dodaj dzień do daty i sprawdź, czy numer miesiąca się zmienia.
  2. Dodaj miesięcy
  3. Jeśli stary termin był "end-of-miesiąca"
    1. Ustawia dzień miesiąca do 1
    2. Dodaj kolejny miesiąc
    3. Odejmij jeden dzień
+0

{ dostać; } ms-help: //MS.VSCC.v90/MS.MSDNQTR.v90.en/fxref_mscorlib/html/899d9772-e792-052a-2c0b-8a28aea0d5b9.htm – sesame

0

Moje podejście do tego problemu zaczyna się od rutyny określa, czy dany dzień jest ostatnim dniem miesiąca (biorąc pod uwagę rok przestępny oczywiście!)

Będziesz także potrzebować procedury, która da ci ostatni dzień miesiąca, biorąc pod uwagę dzień w tym miesiącu. miesiąc.

Następnie, jeśli napotkasz dzień, który jest JEST ostatni dzień, dodaj jeden dzień i użyj drugiej procedury, aby uzyskać ostatni dzień TEGO miesiąca. Użyj pętli przez wiele miesięcy.

0

Można zaimplementować EndOfMonth() i isEndOfMonth().

tak Twój kod będzie bardziej lub mniej,

if isEndOfMonth(this.Date()) 
    endDate = (startmonth + addedMonths).EndOfMonth() 
else 
    endDate = startDate + addedMonths 

Nieco uproszczone, ale masz pomysł.

Istnieje oczywiście alot pomysłów tutaj logiki EndOFMonth i isEndOfMonth

2
DateTime exampleDate = DateTime.Parse("12/31/2009"); 
bool isLastDayOfMonth = (exampleDate.AddDays(1).Month != exampleDate.Month); 

if (isLastDayOfMonth) 
    Console.WriteLine(exampleDate.AddDays(1).AddMonths(1).AddDays(-1)); 
else 
    Console.WriteLine(new DateTime(exampleDate.Year, exampleDate.Month, 1).AddMonths(2).AddDays(-1)); 

EDIT: I znowu czytać swoje pytanie. Musisz sprawdzić, czy ostatni dzień miesiąca.

Przepraszam, żałuję, że nie przeczytałem dokładnie tego, co jest potrzebne.
Mam nadzieję, że jest to wystarczająco dobre, aby dać ci wyobrażenie o tym, co jest potrzebne.

0

Oto proste rozwiązanie .NET C#, który liczy lata przestępne, etc:

static DateTime ContractDue(DateTime start, int months) 
{ 
    if (start.Month == start.AddDays(1).Month) 
    { // Same month, just add the months 
      return start.AddMonths(months); 
    } 
    // Last day of month... add a day, add the months, then go back one day 
    return start.AddDays(1).AddMonths(months).AddDays(-1); 
} 
-1

Jeśli trzeba tylko EndOfMonth lub prosty AddNMonth, to masz już odpowiedź.

W przeciwnym razie, aby mieć kompletne rozwiązanie ogólne, konieczne jest wdrożenie wzorca cyklu, jak można zobaczyć w interfejsie użytkownika urządzenia Outlook Meeting interface. Nie sugeruję jednak korzystania z implementacji Outlooka, ale powinno być kilka komponentów .NET, które można kupić. Lub wdrożyć go samemu, ale nie lekceważ i nie testuj wszystkiego - jest to bardzo trudny element do wdrożenia.

0

Można użyć metody DateTime.DaysInMonth() coś jak następuje:

DateTime workingMonth = new DateTime(2009, 06, 30).AddDays(1); 
int nextMonthDays = DateTime.DaysInMonth(workingMonth.Year, workingMonth.Month); 
DateTime newMonth = new DateTime(workingMonth.Year, workingMonth.Month, nextMonthDays); 
0

Czy to wtedy funkcja uzupełnieniem znaleźć, jeśli jestem na początku miesiąca? DateTime.Now.AddDays(-1).Month == DateTime.Now.AddMonths(-1).Month