Search code examples
iosswiftnsdatenscalendarnsdatecomponents

NSDate extension for specific day of each week


I'm looking to extend the NSDate class so I am able to reference the Tuesday of each week we're currently in as an NSDate.

I understand that this can be done with NSDateComponents. So far I have the below:

extension NSDate {

var tuesday: NSDate {

    let calendar = NSCalendar.currentCalendar()

    let todaysDate = NSDate()

    let weekdayComponents = calendar.components(.CalendarUnitWeekday | .CalendarUnitWeekdayOrdinal, fromDate: todaysDate)

    weekdayComponents.weekday = 3

    let returnTuesday = calendar.dateByAddingComponents(weekdayComponents, toDate: todaysDate, options: nil)

    return returnTuesday!
}}

I believe that the CalendarUnitWeekday work on an index based system (i.e. Sunday = 1, Saturday = 7), which is why I am setting the required weekday to 3 for Tuesday.

However when initialising an NSDate object and accessing this extended 'tuesday' property, I am receiving a date a month in advance.

(todays date - "Aug 26, 2015, 4:42 PM") (tuesday date - "Sep 26, 2015, 4:42 PM")

What is causing this advancement of a month? Is there a way to return a specific date of each week we are in through extending the NSDate class?

Thanks


Solution

  • Rather than using dateByAddingComponents: you can find today's weekday and get its difference with the target weekday and update the day component. The required date can be generated by dateFomComponents method using the updated components parameter.

    extension NSDate {
    
        var tuesday: NSDate {
    
            let calendar = NSCalendar.currentCalendar()
            let components = calendar.components(.CalendarUnitWeekday | .CalendarUnitDay | .CalendarUnitMonth | .CalendarUnitYear | .CalendarUnitHour | .CalendarUnitMinute, fromDate: NSDate())
            let targetDay = 3 //Required day
            let today = components.weekday
    
            if (targetDay < today) {
                components.day -= today - targetDay
            } else {
                components.day += targetDay - today
            }
    
            return calendar.dateFromComponents(components)!
        }}