6
votes

My question is the REVERSE of the typical "How do I find out if an NSDate is between startDate and endDate?"

What I want to do is find ALL NSDATES (to the day, not hour or minute) that occur BETWEEN startDate and endDate. Inclusive of those dates would be preferable, although not necessary.

Example: (I know that these don't represent NSDates, these are just for illustration)

INPUT: startDate = 6/23/10 20:11:30 endDate = 6/27/10 02:15:00

OUTPUT: NSArray of: 6/23/10, 6/24/10, 6/25/10, 6/26/10, 6/27/10

I don't mind doing the work. It's just that I don't know where to start in terms of making efficient code, without having to step through the NSDates little by little.

3

3 Answers

9
votes

Use an NSCalendar instance to convert your start NSDate instance into an NSDateComponents instance, add 1 day to the NSDateComponents and use the NSCalendar to convert that back to an NSDate instance. Repeat the last two steps until you reach your end date.

5
votes

Add 24 hours to the start date until you go past the end date.

for ( nextDate = startDate ; [nextDate compare:endDate] < 0 ; nextDate = [nextDate addTimeInterval:24*60*60] ) {
  // use date
}

You could round the first date to noon or midnight before starting the loop if you care about the time of day.

2
votes

Ever since OS X 10.9 and iOS 8.0 there is the following very clean way to do this. It also deals with end of month jumps.

let cal = NSCalendar.currentCalendar()
let start = NSDate()
let end = // some end date

var next = start
while !cal.isDate(next, inSameDayAsDate: end) {
    next = cal.dateByAddingUnit(.Day, value: 1, toDate: next, options: [])!
    // do something with `next`
}

Note that for older OS versions -isDate:inSameDayAsDate: can be replaced by some call to e.g. -components:fromDate:toDate:options: and -dateByAddingUnit:value:toDate:options: can be replaced by dateByAddingComponents:toDate:options:.