Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Experimenting with creating a SequenceType for iterating over a range of dates. Blogged here: http://adampreble.net/blog/2014/09/iterating-over-range-of-dates-swift/
import Foundation
func > (left: NSDate, right: NSDate) -> Bool {
return left.compare(right) == .OrderedDescending
}
extension NSCalendar {
func dateRange(startDate startDate: NSDate, endDate: NSDate, stepUnits: NSCalendarUnit, stepValue: Int) -> DateRange {
let dateRange = DateRange(calendar: self, startDate: startDate, endDate: endDate, stepUnits: stepUnits, stepValue: stepValue, multiplier: 0)
return dateRange
}
}
struct DateRange : SequenceType {
var calendar: NSCalendar
var startDate: NSDate
var endDate: NSDate
var stepUnits: NSCalendarUnit
var stepValue: Int
private var multiplier: Int
func generate() -> Generator {
return Generator(range: self)
}
struct Generator: GeneratorType {
var range: DateRange
mutating func next() -> NSDate? {
guard let nextDate = range.calendar.dateByAddingUnit(range.stepUnits,
value: range.stepValue * range.multiplier,
toDate: range.startDate,
options: []) else {
return nil
}
if nextDate > range.endDate {
return nil
}
else {
range.multiplier += 1
return nextDate
}
}
}
}
// Usage:
func testDateRange() {
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let startDate = NSDate(timeIntervalSinceNow: 0)
let endDate = NSDate(timeIntervalSinceNow: 24*60*60*7-1)
let dateRange = calendar.dateRange(startDate: startDate,
endDate: endDate,
stepUnits: .Day,
stepValue: 1)
let datesInRange = Array(dateRange)
XCTAssertEqual(datesInRange.count, 7, "Expected 7 days")
XCTAssertEqual(datesInRange.first, startDate, "First date should have been the start date.")
}

The one issue I've found with this, is it seems to skip over the first date you pass to it. I.e. Date 1 (exclusive) to Date N (inclusive)

Yes, the start index is non-inclusive. I guess one needs to implement constructor that will subtract 1 day from start index.

Owner
preble commented Aug 25, 2016

Thanks for the comments pointing out the issue with the first date! I've updated the gist to fix that issue, as well as changed it to be created using an extension on NSCalendar, which I think is more idiomatic for NSCalendar-related date functions.

I'm guessing it's not that easy to create an option to iterate backwards through the range?

Nidhee commented Feb 8, 2017

I move from swift 2.2 to swift 3.0. Which is getting lot of errors. can you help in converting to swift 3.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment