Search code examples
iosobjective-cnsdatenscalendarnsdatecomponents

Counting calendar days in iOS


I've got a task to calculate how many days are left until a certain deadline expires. For example: I have a 10 business days deadline starting today (let's assume it's a Monday). I need to calculate how many calendar days remain until that deadline expires. Which means I need to see how many weekends fall into this time period and add them to the "remaining days" result (which in our concrete example should be 12 days since only one weekend will fall in this timeframe).

How do I do that on iOS?

Let me know if you need more clarification


Solution

  • int numberOfDays=30;
    
    NSDate *startDate=[NSDate date];
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *offset = [[NSDateComponents alloc] init];
    NSMutableArray *dates = [NSMutableArray arrayWithObject:startDate];
    NSMutableArray *weekends = [NSMutableArray new];
    NSMutableArray *businessDays = [NSMutableArray new];
    
    if (![self isDateWeekend:startDate]) {
        [businessDays addObject:startDate];
    }
    
    for (int i = 1; i < numberOfDays; i++) {
        [offset setDay:i];
        NSDate *nextDay = [calendar dateByAddingComponents:offset toDate:startDate options:0];
        [dates addObject:nextDay];
        [businessDays addObject:nextDay];
        if ([self isDateWeekend:nextDay]) {
            [weekends addObject:nextDay];
            [businessDays removeObject:nextDay];
        }
    }
    
    NSLog(@"All Days%@",dates);
    NSLog(@"All Weekends%@",weekends);
    NSLog(@"Business Days%@",businessDays);
    

    The weekend function has been borrowed from an other SO answer as it was neater,

    - (BOOL) isDateWeekend:(NSDate*)date
    {
        NSRange weekdayRange = [[NSCalendar currentCalendar] maximumRangeOfUnit:NSCalendarUnitWeekday];
        NSDateComponents *components = [[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:date];
        NSUInteger weekdayOfDate = [components weekday];
        if (weekdayOfDate == weekdayRange.location || weekdayOfDate == weekdayRange.length) {
                //the date falls somewhere on the first or last days of the week
                return YES;
            }
            else
                return NO;
     }
    

    This can be extended to get all days,weekends and business days within a date range.