I had a need during a recent app build to find out the time until the next recurrance of an event that I had saved.

You think that there’d be something in the API, right? Um, no.

Here I’m sharing with the community the solution that I ended up building myself. I had a UILabel that was called countdownLabel of which I wanted to update to the time left until the next occurrence of an event I had stored in my userdefaults called ‘changeContactsReminder”.

The method of approach is that if we know the events start date and the recurrance rule, then we can work out how long until the next occurrence, and then work the time difference from today.

//UpdateCountdown is the method that is called when we want to update.  I triggered this from viewDidLoad.
-(void) updateCountdown{
    //Obviously we only want to trigger this code when the event actually exists!
    if([userDefaults objectForKey:@"changeContactsReminder"]){
        NSDate *today = [NSDate date];
        EKEvent *myEvent = [eventStore eventWithIdentifier:[userDefaults objectForKey:@"changeContactsReminder"]];
        NSDate *nextEvent = myEvent.startDate;
        EKRecurrenceRule *recurrence = myEvent.recurrenceRule;
        //This will give us the time since the event started
        double timeinterval = [today timeIntervalSinceDate:nextEvent];
        NSLog(@"INTERVAL %f", timeinterval);
        if(timeinterval >0){
            //Find the next date for the occurrence.
            //Different cases depending on the recurrance - only weekly supported here.
            //My app had code for monthly and yearly - the logic is the same (just a different timeblock
            // and component to add in NSDateComponents),
            //omitted for simplicity.
            if(recurrence.frequency == EKRecurrenceFrequencyWeekly){
                //interval is bi-weekly, weekly, etc.
                int interval = recurrence.interval;
                //timeblock is the seconds in a week
                float timeblock = interval*3600*24*7.0;
                float numblocks = fabsf(timeinterval/timeblock);
                NSLog(@"NUMBER OF BLOCKS %f", numblocks);
                //ceil here will give us the number of blocks until the next event, i.e. the upcoming one.
                float total = ceil(numblocks);
                int weekstoadd = total*interval;
                NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
                //Add the number of weeks
                [components setWeek:weekstoadd];
                NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
                nextEvent = [gregorian dateByAddingComponents:components toDate:nextEvent options:0];
            /*  other code for month and year goes here */
        //Now we have the next event stored in nextEvent, we need to work out the time until
        // this happens, and format accordingly
        NSDateComponents *componentsnext = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:nextEvent];
        NSInteger daynext = [componentsnext day];
        NSInteger monthnext = [componentsnext month];
        NSInteger yearnext = [componentsnext year];
        NSLog(@"Year %d Month %d Day %d", yearnext, monthnext, daynext);
        NSCalendar *calendar = [NSCalendar currentCalendar];;
        NSDateComponents *difference = [calendar components:NSDayCalendarUnit | NSMonthCalendarUnit fromDate:today toDate:nextEvent options:0];
        //Here we are formatting the date to a more user friendly format
        if([difference month] == 1 && [difference day] == 1){
            countdownLabel.text = [NSString stringWithFormat:@"%d month %d day", [difference month],[difference day]];
        else if([difference month] == 1 && [difference day] < 1){
            countdownLabel.text = [NSString stringWithFormat:@"%d month", [difference month]];
        else if([difference month] < 1 && [difference day] >1){
            countdownLabel.text = [NSString stringWithFormat:@"%d days",[difference day]];
        else if([difference month]