Я добавляю повторяющиеся события в приложение Какао, над которым я работаю. У меня есть повторение каждый день и каждую неделю, потому что я могу определить их математически (3600 * 24 * 7 = 1 неделя). Я использую следующий код для изменения даты:
[NSDate dateWithTimeIntervalSinceNow:(3600*24*7*(weeks))]
Я знаю, сколько месяцев прошло с тех пор, как событие было повторено, но я не могу понять, как создать объект NSDate, который представляет 1 месяц / 3 месяца / 6 месяцев / 9 месяцев в будущем. В идеале я хочу, чтобы пользователь говорил повторять ежемесячно, начиная с 14 октября, и повторять это будет 14-го числа каждого месяца.





Я, наверное, воспользуюсь NSCalendarDate.
Получите dayOfMonth, monthOfYear и yearOfCommonEra текущей даты в виде трех чисел.
Добавьте необходимое количество месяцев (1/3/6/9), учитывая, 1) существует ли эта дата (например, 31 апреля, 29 февраля в невисокосный год) и 2) продление года.
Создайте эту новую дату с помощью initWithYear: month: day: hour: minute: second: timeZone:
В документации четко указано, что NSCalendarDate использовать не следует.
Использование NSCalendarDate обычно не допускается для приложений iPhone.
(Практически то же самое, что и этот вопрос.)
С документация:
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.
Следуя этому совету:
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];
Может быть более прямая или эффективная реализация, но она должна быть точной и указывать в правильном направлении.
Лучше использовать NSDateCompontents и setMonth равным +1. Тогда вы получите ту же дату, но в следующем месяце. NSDateComponents *components = [gregorian components: NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date]]; [components setMonth://here you set current month+1]; NsDate *nextMonth = [gregorian dateFromComponents:components];
NSCalendarDate больше не поддерживается новым SDK, возникнут проблемы при сборке для распространения.
Используйте 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 месяц по григорианскому календарю».
У меня сейчас нет устройства для тестирования, но что произойдет, если вы перейдете на один месяц 29 января, если это не високосный год? Будет ли это 28 февраля или 1 марта?
Вы можете сделать следующее:
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];
Спасибо. У меня такой же вопрос. :-)