objective c - Calculate the next event from now given an NSDate in the past and a repeat interval -


how can calculate first date later date in past repeating interval? example:

// date in past nsdate *pastdate = [nsdate my_datewithstring:@"11/09/2001"];  // time interval nstimeinterval repeatinterval = 14 * 24 * 60 * 60; // 2 weeks  // current date nsdate *now = [nsdate date]; // 23/07/2015  // start calculating next date -> nsdate *nextdate = /* interval added past date */ // result later now? // no? calculate again // abracadabra  nslog(@"nexdate = %@",nextdate); // 28/07/2015 

i don't want use iterations. i'm concerned calculating case start date 1 year in past , repeat interval of day.

here solution, has iterations.

  nsdatecomponents *twoweeksdatecomponents = [nsdatecomponents new];   twoweeksdatecomponents.weekofmonth = 2;    nsdate *date = self.picker.date;   nscalendar *calendar = [nscalendar currentcalendar];    nsdate *now = [nsdate date];   nsdate *nextdate = date;   nscomparisonresult result = [nextdate compare:now];   while (result == nsorderedascending) {     nextdate = [calendar datebyaddingcomponents:ktwoweeksdatecomponents                                          todate:nextdate                                         options:nscalendarmatchnexttime];     result = [nextdate compare:now];   }   nslog(@"nexdate = %@",nextdate); // 28/07/2015 

you can indeed without iteration, using little arithmetic instead. you're looking nearest multiple of factor f strictly greater value n. it's bit more complicated being calendrical calculation, still arithmetic (and nscalendar of course heavy lifting -- e.g., leap years).

nsdate * pastdate = ...; nsdate * = [nsdate date]; 

get repeat interval user , construct nsdatecomponents representing it:

nscalendarunit repeatunit = nscalendarunitweekofyear; nsuinteger repeatinterval = 2;  nsdatecomponents * repeatcomps = [nsdatecomponents new]; [repeatcomps setvalue:repeatinterval forcomponent:repeatunit]; 

given repeat unit, find amount of unit occurs between 2 dates, date components object:

nscalendar * cal = [nscalendar currentcalendar]; nsdatecomponents * deltacomps = [cal components:repeatunit                                        fromdate:pastdate                                          todate:now                                         options:0]; nsinteger deltaval = [deltacomps valueforcomponent:repeatunit]; 

now comes arithmetical bit. round delta down nearest multiple of repeat interval. adding rounded value (using appropriate unit) produce date equal or earlier now.

now, jawboxer has pointed out, repeatunit of nscalendarunitmonth, unexpected results if calculate date using value , afterwards add 1 more repeat interval (as original version of answer did). instead, add 1 number of repeats immediately; calendar correctly handles month increments.

nsinteger repeatsjustpastnow = 1 + deltaval - (deltaval % repeatinterval);  nsdatecomponents * tonowcomps = [nsdatecomponents new]; [tonowcomps setvalue:repeatsjustpastnow         forcomponent:repeatunit];  nsdate * nextdate; nextdate = [cal datebyaddingcomponents:tonowcomps                                 todate:pastdate                                options:0]; 

jawboxer's swift version of corrected code on github.


Comments

Popular posts from this blog

python - pip install -U PySide error -

arrays - C++ error: a brace-enclosed initializer is not allowed here before ‘{’ token -

cytoscape.js - How to add nodes to Dagre layout with Cytoscape -