Sergey Sergey - 5 months ago 31
Objective-C Question

Get last tuesday in month ios

Can get last weekday in the month through NSDateComponents? For example: last monday in month or last friday in month. etc

Answer

Here's a solution; tested, and fairly robust, I think. We'll let NSCalendar walk through the month, a day at a time, and pull out all matching weekdays as NSDates. Then you can answer questions like, "The 3rd Wednesday of this month"

I believe the comments are clear about what is happening, and why. If you need further clarification, I'll be happy to do so.

//What weekday are we interested in? 1 = Sunday . . . 7 = Saturday
NSInteger targetWeekday = 1;

//Using this methodology, GMT timezone is important to set
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];

//set the components to the first of the current month
NSDateComponents *startComponents = [calendar components:NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
startComponents.day = 1;

//the enumeration starts "afterDate", so shift the start back one day (86400 seconds) to include the 1st of the month
NSDate *startDate = [[calendar dateFromComponents:startComponents] dateByAddingTimeInterval:-86400];

//the enumeration searches for a match; we'll match at the midnight hour and find every occurance of midnight
NSDateComponents *dayByDay = [[NSDateComponents alloc] init];
dayByDay.hour = 0;

//I've opted to put all matching weekdays of the month into an array, so you can find any instance easily
__block NSMutableArray *foundDates = [NSMutableArray arrayWithCapacity:5];
[calendar enumerateDatesStartingAfterDate:startDate
                       matchingComponents:dayByDay
                                  options:NSCalendarMatchPreviousTimePreservingSmallerUnits
                               usingBlock:^(NSDate *date, BOOL exactMatch, BOOL *stop){
                                   NSDateComponents *thisComponents = [calendar components:NSCalendarUnitMonth | NSCalendarUnitWeekday fromDate:date];
                                   //as long as the month stays the same... (or the year, if you wanted to)
                                   if (thisComponents.month == startComponents.month) {

                                       //does this date match our target weekday search?
                                       if (thisComponents.weekday == targetWeekday) {

                                           //then add it to our result array
                                           [foundDates addObject:date];
                                       }

                                   //once the month has changed, we're done
                                   } else {
                                       *stop = YES;
                                   }
                               }];

//Now, with our search result array, we can find the 1st, last, or any specific occurance of that weekday on that month
NSLog(@"Found these: %@", foundDates);

So, if you only wanted the last one, then just use [foundDates lastObject]

Comments