对于比您上面给出的更一般的答案,您可以实现自己的SequenceType
运行/生成NSDate
元素。
修改Adam Preble (Swift < 2.0) 的这篇博客文章SequenceType
DateRange
中的实现,我们可以构造以下内容:
/* Modified version of Adam Preble:s DateRange: http://adampreble.net/blog/2014/09/iterating-over-range-of-dates-swift/ */
func < (left: NSDate, right: NSDate) -> Bool {
return left.compare(right) == NSComparisonResult.OrderedAscending
}
struct DateRange : SequenceType {
var calendar: NSCalendar
var startDate: NSDate
var endDate: NSDate
var stepUnits: NSCalendarUnit
var stepValue: Int
func generate() -> Generator {
return Generator(range: self, firstDate: true)
}
struct Generator: GeneratorType {
var range: DateRange
var firstDate : Bool = true
mutating func next() -> NSDate? {
if firstDate {
firstDate = false
return range.startDate
}
guard let nextDate = range.calendar.dateByAddingUnit(range.stepUnits,
value: range.stepValue, toDate: range.startDate,
options: NSCalendarOptions.MatchFirst) where !(range.endDate < nextDate) else {
return nil
}
range.startDate = nextDate
return nextDate
}
}
}
有了这个,你可以遍历一个NSDate
:s 的范围,就像你可以遍历一个整数范围一样,而不需要明确地需要一个对象数组NSDate
。
示例用法(利用你startOfMonth()
和endOfMonth()
扩展NSDate
):
/* Your NSDate extension */
extension NSDate {
// ... as in your question above
}
/* Example usage */
let formatter = NSDateFormatter()
formatter.dateFormat = "EEE, MMM. d, yyyy"
// print week days of current month, using DateRange (as well as your extension)
if let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian) {
let dateRange = DateRange(calendar: calendar,
startDate: NSDate().startOfMonth,
endDate: NSDate().endOfMonth,
stepUnits: NSCalendarUnit.Day,
stepValue: 1)
for date in dateRange where !calendar.isDateInWeekend(date) {
print(formatter.stringFromDate(date))
}
}
输出:
/* Mon, Feb. 1, 2016
Tue, Feb. 2, 2016
Wed, Feb. 3, 2016
Thu, Feb. 4, 2016
Fri, Feb. 5, 2016
Mon, Feb. 8, 2016
Tue, Feb. 9, 2016
...
Thu, Feb. 25, 2016
Fri, Feb. 26, 2016
Mon, Feb. 29, 2016 */
[NSDate]
数组中一个月的日期(尤其是一个数组,您实际上一次只按顺序使用一个成员。
例如,在下面的示例中使用NSDate
数组将是非常不必要的(并且可能会产生不必要的开销;但是让我们保留它,因为我们希望避免一些评论者提出过早优化的罪过的主题:))
// versatile use of DateRange over somewhat "large" ranges of dates
formatter.dateFormat = "yyyy-MM-dd"
if let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian),
startDate = formatter.dateFromString("2016-01-01"),
endDate = formatter.dateFromString("2016-12-31") {
formatter.dateFormat = "EEE, MMM. d, yyyy"
// initialize dateRange instance
var dateRange = DateRange(calendar: calendar,
startDate: startDate,
endDate: endDate,
stepUnits: NSCalendarUnit.Day,
stepValue: 1)
// print all week days of 2016
for date in dateRange where !calendar.isDateInWeekend(date) {
print(formatter.stringFromDate(date))
}
print("")
// re-use same dateRange instance and print
// all week days of July 2016 -> June 2017
formatter.dateFormat = "yyyy-MM-dd"
if let startDate = formatter.dateFromString("2016-07-01"),
endDate = formatter.dateFromString("2017-06-30") {
// update dateRange instance
dateRange.startDate = startDate
dateRange.endDate = endDate
formatter.dateFormat = "EEE, MMM. d, yyyy"
for date in dateRange where calendar.isDateInWeekend(date) {
print(formatter.stringFromDate(date))
}
}
}
输出:
/* Mon, Feb. 1, 2016
Tue, Feb. 2, 2016
Wed, Feb. 3, 2016
Thu, Feb. 4, 2016
Fri, Feb. 5, 2016
Mon, Feb. 8, 2016
Tue, Feb. 9, 2016
...
Fri, Dec. 23, 2016
Mon, Dec. 26, 2016
Tue, Dec. 27, 2016
Wed, Dec. 28, 2016
Thu, Dec. 29, 2016
Fri, Dec. 30, 2016
// 2nd range print
Fri, Jul. 1, 2016
Mon, Jul. 4, 2016
Tue, Jul. 5, 2016
Wed, Jul. 6, 2016
Thu, Jul. 7, 2016
...
Fri, Jun. 23, 2017
Mon, Jun. 26, 2017
Tue, Jun. 27, 2017
Wed, Jun. 28, 2017
Thu, Jun. 29, 2017
Fri, Jun. 30, 2017 */