Let's suppose that today is Wednesday. I can break an NSDate
down into NSDateComponents
, but I need to find the NSDate
with the next upcoming Monday. If today is Monday, then the next upcoming Monday is today. What's the right way to achieve this?
Find NSDate for the next closest specific day of week for any date
Asked Answered
You can use nextDateAfterDate:
method on NSCalendar
object to achieve this,
let now = Date() // today
var matchingComponents = DateComponents()
matchingComponents.weekday = 2 // Monday
let comingMonday = Calendar.current.nextDate(after: now,
matching: matchingComponents,
matchingPolicy:.nextTime)
Here, is a simple method to find next monday. If today is Monday the following function returns today or else the closest next Monday. Note that it uses en_POSIX_US such that the days can be matched. When the locale is en_POSIX_US, weekdays symbols become,
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
And, here is how this days could be used,
func findNext(_ day: String, afterDate date: Date) -> Date? {
var calendar = Calendar.current
calendar.locale = Locale(identifier: "en_US_POSIX")
let weekDaySymbols = calendar.weekdaySymbols
let indexOfDay = weekDaySymbols.index(of: day)
assert(indexOfDay != nil, "day passed should be one of \(weekDaySymbols), invalid day: \(day)")
let weekDay = indexOfDay! + 1
let components = calendar.component(.weekday, from: date)
if components == weekDay {
return date
}
var matchingComponents = DateComponents()
matchingComponents.weekday = weekDay // Monday
let nextDay = calendar.nextDate(after: date,
matching: matchingComponents,
matchingPolicy:.nextTime)
return nextDay!
}
let nextMonday = findNext("Monday", afterDate: Date())
let mondayAfterThat = findNext("Monday", afterDate: nextMonday!)
let thursday = findNext("Thursday", afterDate: mondayAfterThat!)
this is the best solution I think:) –
Dogooder
It's amazing that
NSCalendar
's iOS 8 methods are still undocumented on the reference library. –
Lighting Yes, they seem to have added many new apis to NSCalendar and siblings. It would be really good to have them documented. –
Weinstein
"Monday" will not work for other languages,
Monday
in polish is Poniedziałek
for instance. I think that searching by name is not the best solution since calendars in devices are automatically localised. –
Dogooder That is the reason that locale is used for the calendar with en_US_POSIX, see that it uses the system calendar but sets locale to en_US_POSIX, just to extract english name. –
Weinstein
for target iOS >= 8 use GeneratorOfOne's solution
else you can use this
let now = NSDate()
var lastMonday:NSDate?
var nextMonday:NSDate?
var start:NSDate?
var interval:NSTimeInterval = 0 // holds the length of a week. can differ for Daylight Saving Time
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)! // have a own calendar object for this calculation to guarantee that the next line does not influence other calculations
cal.firstWeekday = 2 // make sure first day of week is Monday.
cal.rangeOfUnit(NSCalendarUnit.CalendarUnitWeekOfMonth, startDate: &lastMonday, interval:&interval, forDate: now) // monday of current week
nextMonday = lastMonday?.dateByAddingTimeInterval(interval) // add a weeks length to the last weeks's monday
println(nextMonday)
You can get the week day by using NSDateComponents
and calculate the interval days, then use dateByAddingTimeInterval
from NSDate
like so:
let now = NSDate()
let calendar: NSDateComponents = NSCalendar.currentCalendar().components(NSCalendarUnit.CalendarUnitWeekday, fromDate: now)
let weekday = calendar.weekday // 1 = Sunday, 2 = Monday
// You get input the weekday here and calculate the interval
// exmaple for moving to the next day
let expectedDate = now.dateByAddingTimeInterval(1 * 24 * 60 * 60)
// exmaple for moving to yesterday
let yesterday = now.dateByAddingTimeInterval(-1 * 24 * 60 * 60)
Don't use 24*60*60 seconds as the duration of a day (think of daylight saving time transitions). –
Locklear
@MartinR sorry. I don't follow. Can you explain this again? –
Goldofpleasure
days can be 23, 24, 25 hours long, due to Daylight Saving Times –
Madlynmadman
© 2022 - 2024 — McMap. All rights reserved.
mt_startOfNextWeek;
method. – Weaponeer