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.") | |
} |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
FrancisBaileyH
commented
Mar 25, 2015
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) |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
alexeyismirnov
Aug 25, 2015
Yes, the start index is non-inclusive. I guess one needs to implement constructor that will subtract 1 day from start index.
alexeyismirnov
commented
Aug 25, 2015
Yes, the start index is non-inclusive. I guess one needs to implement constructor that will subtract 1 day from start index. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
preble
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.
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. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
leeprobert
Nov 16, 2016
I'm guessing it's not that easy to create an option to iterate backwards through the range?
leeprobert
commented
Nov 16, 2016
I'm guessing it's not that easy to create an option to iterate backwards through the range? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
Nidhee
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
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 |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
aaronfalls
May 26, 2017
@Nidhee you probably don't need this still, but I updated for Swift 3 today :)
aaronfalls
commented
May 26, 2017
@Nidhee you probably don't need this still, but I updated for Swift 3 today :) |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
Show comment Hide comment
phatmann
Dec 7, 2017
For Swift 4:
extension Calendar {
func dateRange(startDate: Date, endDate: Date, component: Calendar.Component, step: Int) -> DateRange {
let dateRange = DateRange(calendar: self, startDate: startDate, endDate: endDate, component: component, step: step, multiplier: 0)
return dateRange
}
}
struct DateRange : Sequence, IteratorProtocol {
var calendar: Calendar
var startDate: Date
var endDate: Date
var component: Calendar.Component
var step: Int
var multiplier: Int
mutating func next() -> Date? {
guard let nextDate = calendar.date(byAdding: component, value: step * multiplier, to: startDate)
else {
return nil
}
if nextDate > endDate {
return nil
} else {
multiplier += 1
return nextDate
}
}
}
phatmann
commented
Dec 7, 2017
For Swift 4:
|
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)