How do I get the actual date of the month based on a given a day ? For example, I would like to retrieve all the dates in June 2017 which are Saturday. How can I achieve that ? Sample code will be very much appreciated as I have struggled for days on this.
A DateComponents
has a weekday
property, representing the day of the week. The weekdays are (in Foundation's Gregorian calendar) numbered 1 for Sunday, 2 for Monday, …, and 7 for Saturday.
A DateComponents
also has a weekdayOrdinal
property, representing “the position of the weekday within the next larger calendar unit, such as the month. For example, 2 is the weekday ordinal unit for the second Friday of the month.”
So let's initialize a DateComponents
for some Saturday in June 2017. It's generally a good idea to specify a time of noon if you don't care about the time, because midnight (the default time of day) can cause problems in some time zones on some days.
var components = DateComponents(era: 1, year: 2017, month: 06, hour: 12, weekday: 7)
And let's make a calendar.
var calendar = Calendar.autoupdatingCurrent
Now we can loop over all the possible weekday ordinals. For each, we'll ask the calendar to generate a date. Then we ask the calendar to convert the date back to year, month, and day components.
In the Gregorian calendar, some months have 5 Saturdays, but most have 4. So when we ask for the 5th Saturday, we'll probably get a date in the following month. When that happens, we want to suppress that date.
for i in 1 ... 5 {
components.weekdayOrdinal = i
let date = calendar.date(from: components)!
let ymd = calendar.dateComponents([.year, .month, .day], from: date)
guard ymd.month == components.month else { break }
print("\(ymd.year!)-\(ymd.month!)-\(ymd.day!)")
}
Output:
2017-6-3
2017-6-10
2017-6-17
2017-6-24
Objective-C version:
NSDateComponents *components = [NSDateComponents new];
components.era = 1;
components.year = 2017;
components.month = 6;
components.hour = 12;
components.weekday = 7;
NSCalendar *calendar = NSCalendar.autoupdatingCurrentCalendar;
for (NSInteger i = 1; i <= 5; ++i) {
components.weekdayOrdinal = i;
NSDate *date = [calendar dateFromComponents:components];
NSDateComponents *ymd = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
if (ymd.month != components.month) { break; }
NSLog(@"%ld-%ld-%ld", (long)ymd.year, (long)ymd.month, (long)ymd.day);
}