Modifying NSDate to represent 1 month from today

22,345

Solution 1

(Almost the same as this question.)

From the documentation:

Use of NSCalendarDate strongly discouraged. It is not deprecated yet, however it may be in the next major OS release after Mac OS X v10.5. For calendrical calculations, you should use suitable combinations of NSCalendar, NSDate, and NSDateComponents, as described in Calendars in Dates and Times Programming Topics for Cocoa.

Following that advice:

NSDate *today = [NSDate date];

NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDateComponents *components = [[NSDateComponents alloc] init];
components.month = 1;
NSDate *nextMonth = [gregorian dateByAddingComponents:components toDate:today options:0];
[components release];

NSDateComponents *nextMonthComponents = [gregorian components:NSYearCalendarUnit | NSMonthCalendarUnit fromDate:nextMonth];

NSDateComponents *todayDayComponents = [gregorian components:NSDayCalendarUnit fromDate:today];

nextMonthComponents.day = todayDayComponents.day;
NSDate *nextMonthDay = [gregorian dateFromComponents:nextMonthComponents];

[gregorian release];

There may be a more direct or efficient implementation, but this should be accurate and should point in the right direction.

Solution 2

Use NSCalender, NSDateComponents and NSDate:

NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
components.month = 1;
NSDate *oneMonthFromNow = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:[NSDate date] options:0];

Just set the different properties of components to get different periods of time (e.g. 3 months, 6 months etc).

Note: Depending on the context, you may want to use [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease] instead of [NSCalendar currentCalendar], if by "1 month" you mean "1 month on the Gregorian calendar".

Share:
22,345
bmalicoat
Author by

bmalicoat

I'm a current CS student at Michigan State University. I have released 5 games and applications for T-Mobile's Sidekick and 1 application for Apple's iPhone. My main interests are game development and mobile software development.

Updated on July 17, 2020

Comments

  • bmalicoat
    bmalicoat almost 4 years

    I'm adding repeating events to a Cocoa app I'm working on. I have repeat every day and week fine because I can define these mathematically (3600*24*7 = 1 week). I use the following code to modify the date:

    [NSDate dateWithTimeIntervalSinceNow:(3600*24*7*(weeks))]
    

    I know how many months have passed since the event was repeated but I can't figure out how to make an NSDate object that represents 1 month/3 months/6 months/9 months into the future. Ideally I want the user to say repeat monthly starting Oct. 14 and it will repeat the 14th of every month.

  • mmalc
    mmalc over 15 years
    The documentation makes clear that NSCalendarDate should not be used.
  • oberbaum
    oberbaum over 14 years
    use of the NSCalendarDate is generally not accepted for iPhone Apps.
  • lagos
    lagos almost 12 years
    Is better to use NSDateCompontents and setMonth to +1. Then you get same date but in next month. NSDateComponents *components = [gregorian components: NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date]]; [components setMonth://here you set current month+1]; NsDate *nextMonth = [gregorian dateFromComponents:components];
  • Jack Humphries
    Jack Humphries almost 11 years
    I don't have a device to test with right now, but what would happen if you go forward by one month on January 29 if it's not a leap year? Would the day be February 28 or March 1?