Modificando NSDate para representar 1 mês a partir de hoje
-
06-07-2019 - |
Pergunta
Eu estou adicionando eventos repetidos para um aplicativo de cacau que estou trabalhando. Eu tenho repetir todos os dias e semana muito bem porque eu posso defini-los matematicamente (3600 * 24 * 7 = 1 semana). Eu uso o seguinte código para modificar a data:
[NSDate dateWithTimeIntervalSinceNow:(3600*24*7*(weeks))]
Eu sei quantos meses se passaram desde que o evento foi repetido, mas eu não consigo descobrir como fazer com que um objeto NSDate que representa 1 mês / 3 meses / 6 meses / 9 meses no futuro. Idealmente, eu quero que o usuário dizer repetição mensal começando 14 de outubro e vai repetir o dia 14 de cada mês.
Solução
(quase o mesmo que esta pergunta .)
A partir da documentação :
O uso de NSCalendarDate fortemente desencorajado. Ainda não está obsoleto, no entanto, pode ser na próxima grande OS liberar após Mac OS X v10.5. Para cálculos de calendário, você deve utilizar combinações adequadas de NSCalendar, NSDate, e NSDateComponents, tal como descrito em Calendários em Datas e Horários Programação Tópicos para Cacau .
A seguir esse conselho:
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];
Pode haver uma implementação mais direta ou eficientes, mas isso deve ser precisa e deve apontar na direção certa.
Outras dicas
Use NSCalender, NSDateComponents e NSDate:
NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
components.month = 1;
NSDate *oneMonthFromNow = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:[NSDate date] options:0];
Basta definir as diferentes propriedades de components
para obter diferentes períodos de tempo (por exemplo, 3 meses, 6 meses, etc).
Nota:. Dependendo do contexto, você pode querer usar [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease]
vez de [NSCalendar currentCalendar]
, se por "um mês" quer dizer "1 mês no calendário gregoriano"
Eu provavelmente vou usar NSCalendarDate.
Obter do data atual dayOfMonth, monthOfYear e yearOfCommonEra, como três números.
Adicione o número necessário de meses (1/3/6/9), tendo o cuidado de 1) se a existência de data (por exemplo, 31 de abril de 29 de fevereiro em um ano não bissexto), e 2) roll-over de ano.
Criar esse novo encontro com initWithYear de NSCalendarDate: mês: dia: hora: minuto: segundo: Fuso horário:
NSCalendarDate não é mais suportado pelo novo SDK, terá problema, enquanto a construção para distribuição.
Você pode fazer como a seguir:
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];