The algorithm is not very spectacular:
- Calculate start of current week
- Use result from 1 to calculate start of next week
- Use result from 2 to calculate start of week after next week
- Date is in next week if its on or after the start of next week and before the start of the week after next week
NSCalendar does most of the work for us. But it looks still a bit intimidating, at least if you don't use these date methods often. You should read the documentation of all of these methods to understand them.
let calendar = NSCalendar.currentCalendar()
let date = NSDate()
var startOfThisWeek: NSDate?
if !calendar.rangeOfUnit(.CalendarUnitWeekOfMonth, startDate: &startOfThisWeek, interval: nil, forDate: date) {
fatalError("Can't calculate start of this week")
}
let startOfNextWeek = calendar.dateByAddingUnit(.CalendarUnitWeekOfMonth, value: 1, toDate: startOfThisWeek!, options: nil)!
let startOfNextNextWeek = calendar.dateByAddingUnit(.CalendarUnitWeekOfMonth, value: 1, toDate: startOfNextWeek, options: nil)!
Just switch .CalendarUnitWeekOfMonth
with .CalendarUnitMonth
and you get the calculation for this, next and the following month.
var startOfThisMonth: NSDate?
if !calendar.rangeOfUnit(.CalendarUnitMonth, startDate: &startOfThisMonth, interval: nil, forDate: date) {
fatalError("Can't calculate start of this month")
}
let startOfNextMonth = calendar.dateByAddingUnit(.CalendarUnitMonth, value: 1, toDate: startOfThisMonth!, options: nil)!
let startOfNextNextMonth = calendar.dateByAddingUnit(.CalendarUnitMonth, value: 1, toDate: startOfNextMonth, options: nil)!
And the test:
let testDate = NSDate(timeIntervalSinceNow: 7*24*60*60)
if startOfThisWeek <= testDate && testDate < startOfNextWeek {
println("\(testDate) is this week")
}
if startOfNextWeek <= testDate && testDate < startOfNextNextWeek {
println("\(testDate) is next week")
}
if startOfThisMonth <= testDate && testDate < startOfNextMonth {
println("\(testDate) is this month")
}
if startOfNextMonth <= testDate && testDate < startOfNextNextMonth {
println("\(testDate) is next month")
}
Result:
"2015-03-22 02:55:19 +0000 is next week"
"2015-03-22 02:55:19 +0000 is this month"
Sounds right.
And if you want to use <=
, ==
, <
etc. instead of the ugly (and confusing) NSComparisonResult
you need this as well:
public func ==(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs === rhs || lhs.compare(rhs) == .OrderedSame
}
public func <(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.compare(rhs) == .OrderedAscending
}
extension NSDate: Comparable { }
This is iOS8 code. If you want to write code that works on older versions you have to replace dateByAddingUnit:value::toDate:options:
by good old NSDateComponents. i.e:
let offSetComponents = NSDateComponents()
offSetComponents.weekOfMonth = 1
let startOfNextWeek = calendar.dateByAddingComponents(offSetComponents, toDate: startOfThisWeek, options: nil)