Изменение NSDate для представления 1 месяца с сегодняшнего дня

Я добавляю повторяющиеся события в приложение Cocoa, над которым я работаю. Я повторяю каждый день и неделю отлично, потому что я могу определить их математически (3600 * 24 * 7 = 1 неделя). Для изменения даты я использую следующий код:

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

Я знаю, сколько месяцев прошло с момента повторения события, но я не могу понять, как создать объект NSDate, который представляет собой 1 месяц /3 месяца/6 месяцев /9 месяцев в будущем. В идеале я хочу, чтобы пользователь произносил повтор, начиная с 14 октября, и он повторял 14 числа каждого месяца.

Ответы

Ответ 1

(Почти так же, как этот вопрос.)

Из documentation:

Использование NSCalendarDate сильно не рекомендуется. Он еще не устарел, однако это может быть в следующей крупной ОС релиз после Mac OS X v10.5. Для календарных расчетов, вы должны используйте подходящие комбинации NSCalendar, NSDate и NSDateComponents, как описано в Календари в Даты и время Темы программирования для Cocoa.

Следуя этому совету:

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];

Возможно, существует более прямая или эффективная реализация, но это должно быть точным и должно указывать в правильном направлении.

Ответ 2

Используйте NSCalender, NSDateComponents и NSDate:

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

Просто установите различные свойства components для получения разных периодов времени (например, 3 месяца, 6 месяцев и т.д.).

Примечание. В зависимости от контекста вы можете использовать [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease] вместо [NSCalendar currentCalendar], если на "1 месяц" вы имеете в виду "1 месяц в григорианском календаре".

Ответ 3

Я, вероятно, буду использовать NSCalendarDate.

Получить текущую дату dateOfMonth, monthOfYear и yearOfCommonEra, как три числа.

Добавьте необходимое количество месяцев (1/3/6/9), соблюдая 1) существует ли эта дата (например, 31 апреля, 29 февраля в течение несезонного года) и 2) перевертывание год.

Создайте эту новую дату с помощью NSCalendarDate initWithYear: month: day: hour: minute: second: timeZone:

Ответ 4

NSCalendarDate больше не поддерживается новым SDK, будет возникать проблема при создании для распространения.

Ответ 5

Вы можете сделать следующее:

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 | NSDayCalendarUnit fromDate:nextMonth];
NSDate *nextMonthDay = [gregorian dateFromComponents:nextMonthComponents];

[gregorian release];