Modificando NSDate para representar 1 mes a partir de hoy
-
06-07-2019 - |
Pregunta
Estoy agregando eventos repetidos a una aplicación Cocoa en la que estoy trabajando. He repetido todos los días y semanas bien porque puedo definirlos matemáticamente (3600 * 24 * 7 = 1 semana). Utilizo el siguiente código para modificar la fecha:
[NSDate dateWithTimeIntervalSinceNow:(3600*24*7*(weeks))]
Sé cuántos meses han pasado desde que se repitió el evento, pero no puedo entender cómo hacer un objeto NSDate que represente 1 mes / 3 meses / 6 meses / 9 meses en el futuro. Idealmente, quiero que el usuario diga repetir mensualmente a partir del 14 de octubre y se repetirá el 14 de cada mes.
Solución
(Casi lo mismo que esta pregunta .)
De la documentación :
Uso de NSCalendarDate fuertemente desanimado. Todavía no está en desuso, sin embargo, puede estar en el próximo sistema operativo principal lanzamiento después de Mac OS X v10.5. por cálculos calendáricos, deberías utilizar combinaciones adecuadas de NSCalendar, NSDate y NSDateComponents, como se describe en Calendarios en Fechas y horas Temas de programación para el cacao .
Siguiendo ese consejo:
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];
Puede haber una implementación más directa o eficiente, pero debe ser precisa y apuntar en la dirección correcta.
Otros consejos
Use NSCalender, NSDateComponents y NSDate:
NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
components.month = 1;
NSDate *oneMonthFromNow = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:[NSDate date] options:0];
Simplemente configure las diferentes propiedades de componentes
para obtener diferentes períodos de tiempo (por ejemplo, 3 meses, 6 meses, etc.).
Nota: Según el contexto, es posible que desee utilizar [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar] autorelease]
en lugar de [NSCalendar currentCalendar]
, si es " 1 mes " te refieres a "1 mes en el calendario gregoriano".
Probablemente usaré NSCalendarDate.
Obtenga la fecha actual dayOfMonth, monthOfYear y yearOfCommonEra, como tres números.
Agregue el número requerido de meses (1/3/6/9), teniendo en cuenta 1) si esa fecha existe (por ejemplo, 31 de abril, 29 de febrero en un año no bisiesto) y 2) transferencia de año.
Crea esa nueva fecha con initWithYear de NSCalendarDate: mes: día: hora: minuto: segundo: timeZone:
NSCalendarDate ya no es compatible con el nuevo SDK, tendrá problemas al compilar para la distribución.
Puede hacer lo siguiente:
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];