views:

618

answers:

9

Hi guys

Just wondering if any know of an elegant solution for the following.

If I have 30 June 2009 and I add a month I want it to go to 31 July 2009, not the 30 July 2009.

This logic is based on the fact that the 30 June 2009 was the end of the month of June and when I add a month I want to go to the end of the next month.

But if I have 29 June 2009 and I add a month it should go to 29 July 2009.

Note I need to be able to add any number of months and I need to take into account leap years.

Also I know the logic here is questionable but it is a business requirement that works with end of month contracts going to the end of the month for a month in the future.

I have thought of several solution but none that are very elegant. Hence I was thinking someone might have a better way.

Cheers Anthony

+16  A: 

To check if a date is the end of the month, you check if the next day is day one of some month. your algorithm should then be "If the day is not end of month, add 1 month. If it is the end of the month, add one day, add one month, subtract one day."

    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);
    }
Jimmy
What about the 31 Dec 2009 + 2 months. Should be 28 Feb 2010...
vdh_ant
sorry, I made a mistake in the explanation "add one day, add one month, subtract one month" should be "add day, add month, subtract day." I fixed that last sentence.
Jimmy
your example still works because you add 2 months to 1 Jan 2010, getting 1 mar 2010, then subtracting the 1 day to get "1 day before the next month", which is equivalent to "last day of month"
Jimmy
A: 

Can you get there by starting at the first day of the previous month and going back one day?

duffymo
A: 
  1. Test to see if the old date is "end-of-month".
    1. Add a day to the date and see if the month number changes.
  2. Add a month
  3. If the old date was "end-of-month"
    1. Set the day of month to 1
    2. Add another month
    3. Subtract one day
Lee
public int Day { get; } ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/fxref_mscorlib/html/899d9772-e792-052a-2c0b-8a28aea0d5b9.htm
sesame
A: 

My approach to this problem would begin with having a routine that determines if a given day is the last day of the month (taking into account leap year Februaries of course!)

You'll also need a routine that gives you the last day of a month, given a day in that month.

Then, if you encounter a day that IS a last day, add one day, and use the second routine to get the last day of THAT month. Use a loop for multiple months.

Charlie Salts
A: 

You could implement a EndOfMonth() and isEndOfMonth().

so your code would be, more or less,

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

A bit simplistic but you get the idea.

There is of course alot of ideas here for the logic of EndOFMonth and isEndOfMonth

paan
A: 
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 read your question again. You will need to put a check to see if its last day of the month.

Sorry, I wish I had read the question clearly of what is needed.
Hope this is good enough to give you an idea of what is needed.

shahkalpesh
A: 

Here is a simple .NET C# solution that counts for leap years, 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);
}
John Rasch
A: 

If you need only EndOfMonth or simple AddNMonth, then you have got your answer already.

Otherwise, to have a complete generic solution you would need an implementation of the Recurrence pattern as you may see it in the UI of the Outlook Meeting interface. I am not suggesting you to use Outlook implementation though, but there should be a few .NET components that you can buy. Or implement it yourself, but do not underestimate and unit-test it all - it is a very tricky component to implement.

van
A: 

You could use the DateTime.DaysInMonth() method something like the following:

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