How to Get All the Sundays in Array of Date iOS

Sort an array of dates to extract every sundays

First store the dates as NSDate objects as you should always store data using the most appropriate data type:

NSArray *datesAsStrings = ...;
NSMutableArray *dates = [NSMutableArray new];
NSDateFormatter *dateFormatter = [NSDateFormatter new];
dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];
dateFormatter.dateFormat = @"yyyy-MM-dd";
for (NSString *dateStr in datesAsStrings) {
NSDate *date = [dateFormatter dateFromString:dateStr];
[dates addObject:dates];
}

and then filter out the sundays:

NSMutableArray *sundays = [NSMutableArray new];
[dates enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop)) {
NSDate *date = (NSDate *)obj;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comps = [calendar components:NSWeekdayCalendarUnit
fromDate:date];
if (comps.weekday == 1)
[sundays addObject:date];
}];

How to Get all Sundays in a month

OK here goes, assuming you also want your output as an array of strings in the format "September 1 2013"...

// Input array
NSArray *array = @[@"September 2013", @"February 2013", @"October 2013", @"January 2013", @"July 2013", @"May 2013"];

// Output array
NSMutableArray *output = [NSMutableArray array];

// Setup a date formatter to parse the input strings
NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
inputFormatter.dateFormat = @"MMMM yyyy";

// Setup a date formatter to format the output strings
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
outputFormatter.dateFormat = @"MMMM d yyyy";

// Gregorian calendar for use in the loop
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

// Iterate each entry in the array
for (NSString *monthYear in array)
{
@autoreleasepool
{
// Parse the entry to get the date at the start of each month and it's components
NSDate *startOfMonth = [inputFormatter dateFromString:monthYear];
NSDateComponents *dateComponents = [calendar components:NSMonthCalendarUnit | NSYearCalendarUnit fromDate:startOfMonth];

// Iterate the days in this month
NSRange dayRange = [calendar rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:startOfMonth];
for (ushort day = dayRange.location; day <= dayRange.length; ++day)
{
@autoreleasepool
{
// Assign the current day to the components
dateComponents.day = day;

// Create a date for the current day
NSDate *date = [calendar dateFromComponents:dateComponents];

// Sunday is day 1 in the Gregorian calendar (https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSDateComponents_Class/Reference/Reference.html#//apple_ref/occ/instm/NSDateComponents/weekday)
NSDateComponents *components = [calendar components:NSWeekdayCalendarUnit fromDate:date];
if (components.weekday == 1)
{
[output addObject:[outputFormatter stringFromDate:date]];
}
}
}
}
}

NSLog(@"%@", output);

// Release inputFormatter, outputFormatter, and calendar if not using ARC

There may be better ways of doing this, I'm not massively happy with it but it does the job.

Find Sunday and Monday with NSCalendar Swift

You can get the start end end of the month, enumerate all days in a month (you can use noon), check if the resulting day is less than the end date otherwise stop the enumeration. Then you just need to check if the date's weekday is equal to Sunday or Monday (1 or 2) and add it to the collection:



extension Date {
func startOfMonth(using calendar: Calendar = .current) -> Date {
calendar.dateComponents([.calendar, .year, .month], from: self).date!
}
func startOfNextMonth(using calendar: Calendar = .current) -> Date {
calendar.date(byAdding: .month, value: 1, to: startOfMonth(using: calendar))!
}
func weekday(using calendar: Calendar = .current) -> Int {
calendar.component(.weekday, from: self)
}
}


let now = Date()
let calendar = Calendar(identifier: .iso8601)
let start = now.startOfMonth(using: calendar)
let end = now.startOfNextMonth(using: calendar)
var dates: [Date] = []

calendar.enumerateDates(startingAfter: start, matching: DateComponents(hour: 12), matchingPolicy: .strict) { (date, _, stop) in
guard let date = date, date < end else {
stop = true
return
}
if 1...2 ~= date.weekday(using: calendar) { dates.append(date) }
}

dates.forEach {
print($0.description(with: .current))
}

This will print

Sunday, October 4, 2020 at 12:00:00 PM BRST

Monday, October 5, 2020 at 12:00:00 PM BRST

Sunday, October 11, 2020 at 12:00:00 PM BRST

Monday, October 12, 2020 at 12:00:00 PM BRST

Sunday, October 18, 2020 at 12:00:00 PM BRST

Monday, October 19, 2020 at 12:00:00 PM BRST

Sunday, October 25, 2020 at 12:00:00 PM BRST

Monday, October 26, 2020 at 12:00:00 PM BRST

Swift - Get next date from a array of weekdays

Never use 86400 for date math, Calendar and IndexSethave powerful methods to do that:

// Put your weekday indexes in an `IndexSet`
let weekdaySet = IndexSet([1, 2, 4, 7]) // Sun, Mon, Wed and Sat

// Get the current calendar and the weekday from today
let calendar = Calendar.current
var weekday = calendar.component(.weekday, from: Date())

// Calculate the next index
if let nextWeekday = weekdaySet.integerGreaterThan(weekday) {
weekday = nextWeekday
} else {
weekday = weekdaySet.first!
}

// Get the next day matching this weekday
let components = DateComponents(weekday: weekday)
calendar.nextDate(after: Date(), matching: components, matchingPolicy: .nextTime)

Swift - Get last 7 days starting from today in array

Use NSCalendar and NSDateComponents:

let cal = NSCalendar.currentCalendar()
// start with today
var date = cal.startOfDayForDate(NSDate())

var days = [Int]()

for i in 1 ... 7 {
// get day component:
let day = cal.component(.DayCalendarUnit, fromDate: date)
days.append(day)

// move back in time by one day:
date = cal.dateByAddingUnit(.DayCalendarUnit, value: -1, toDate: date, options: nil)!
}

println(days)

Update for Swift 2.2 (Xcode 7.3.1):

let cal = NSCalendar.currentCalendar()
var date = cal.startOfDayForDate(NSDate())
var days = [Int]()
for i in 1 ... 7 {
let day = cal.component(.Day, fromDate: date)
days.append(day)
date = cal.dateByAddingUnit(.Day, value: -1, toDate: date, options: [])!
}
print(days)

Update for Swift 3 (Xcode 8 beta 2):

let cal = Calendar.current
var date = cal.startOfDay(for: Date())
var days = [Int]()
for i in 1 ... 7 {
let day = cal.component(.day, from: date)
days.append(day)
date = cal.date(byAdding: .day, value: -1, to: date)!
}
print(days)

Get array of dates for hours, days, weeks, months between current date/time and end date/time

This is what I went with - stuck with "the loop" :S

func monthsInYear() {
print()
print("monthsInYear")

var calendar = Calendar.current
let date = Date()
let monthsOfYearRange = calendar.range(of: .month, in: .year, for: date)
//print(monthsOfYearRange as Any)

if let monthsOfYearRange = monthsOfYearRange {
let year = calendar.component(.year, from: date)

for monthOfYear in (monthsOfYearRange.lowerBound..<monthsOfYearRange.upperBound) {
let components = DateComponents(year: year, month: monthOfYear)
guard let date = Calendar.current.date(from: components) else { continue }
print(date.description(with: Locale.current))
}
}
}

func weeksInMonths() {
print()
print("weeksInMonths")

var calendar = Calendar.current
let date = Date()
let weekOfYearRange = calendar.range(of: .weekOfYear, in: .month, for: date)
//print(weekOfYearRange as Any)

if let weekOfYearRange = weekOfYearRange {
let year = calendar.component(.year, from: date)

for weekOfYear in (weekOfYearRange.lowerBound..<weekOfYearRange.upperBound) {
let components = DateComponents(weekOfYear: weekOfYear, yearForWeekOfYear: year)
guard let date = Calendar.current.date(from: components) else { continue }
print(date.description(with: Locale.current))
}
}
}

func daysInWeek() {
print()
print("daysInWeek")

var calendar = Calendar.current
let date = Date()
let daysInWeekRange = calendar.range(of: .day, in: .weekOfMonth, for: date)
//print(daysInWeekRange as Any)

if let daysInWeekRange = daysInWeekRange {
let year = calendar.component(.year, from: date)
let month = calendar.component(.month, from: date)
let weekOfMonth = calendar.component(.weekOfMonth, from: date)

for dayOfWeek in (daysInWeekRange.lowerBound..<daysInWeekRange.upperBound) {
let components = DateComponents(month: month, day: dayOfWeek, weekOfMonth: weekOfMonth)
guard let date = Calendar.current.date(from: components) else { continue }
print(date.description(with: Locale.current))
}
}
}

func hoursInDay() {
print()
print("hoursInDay")

var calendar = Calendar.current
let date = Date()
let hoursInDayRange = calendar.range(of: .hour, in: .day, for: date)
//print(hoursInDayRange as Any)

if let hoursInDayRange = hoursInDayRange {
let year = calendar.component(.year, from: date)
let month = calendar.component(.month, from: date)
let weekOfMonth = calendar.component(.weekOfMonth, from: date)
let day = calendar.component(.day, from: date)

for hourOfDay in (hoursInDayRange.lowerBound..<hoursInDayRange.upperBound) {
let components = DateComponents(year: year, month: month, day: day, hour: hourOfDay, weekOfMonth: weekOfMonth)
guard let date = Calendar.current.date(from: components) else { continue }
print(date.description(with: Locale.current))
}
}
}

Which produces the following output when run:

monthsInYear
Sunday, January 1, 2017 at 12:00:00 AM Eastern Standard Time
Wednesday, February 1, 2017 at 12:00:00 AM Eastern Standard Time
Wednesday, March 1, 2017 at 12:00:00 AM Eastern Standard Time
Saturday, April 1, 2017 at 12:00:00 AM Eastern Daylight Time
Monday, May 1, 2017 at 12:00:00 AM Eastern Daylight Time
Thursday, June 1, 2017 at 12:00:00 AM Eastern Daylight Time
Saturday, July 1, 2017 at 12:00:00 AM Eastern Daylight Time
Tuesday, August 1, 2017 at 12:00:00 AM Eastern Daylight Time
Friday, September 1, 2017 at 12:00:00 AM Eastern Daylight Time
Sunday, October 1, 2017 at 12:00:00 AM Eastern Daylight Time
Wednesday, November 1, 2017 at 12:00:00 AM Eastern Daylight Time
Friday, December 1, 2017 at 12:00:00 AM Eastern Standard Time

weeksInMonths
Sunday, November 26, 2017 at 12:00:00 AM Eastern Standard Time
Sunday, December 3, 2017 at 12:00:00 AM Eastern Standard Time
Sunday, December 10, 2017 at 12:00:00 AM Eastern Standard Time
Sunday, December 17, 2017 at 12:00:00 AM Eastern Standard Time
Sunday, December 24, 2017 at 12:00:00 AM Eastern Standard Time
Sunday, December 31, 2017 at 12:00:00 AM Eastern Standard Time

daysInWeek
Monday, December 10, 1 at 12:00:00 AM GMT-04:56:02
Tuesday, December 11, 1 at 12:00:00 AM GMT-04:56:02
Wednesday, December 12, 1 at 12:00:00 AM GMT-04:56:02
Thursday, December 13, 1 at 12:00:00 AM GMT-04:56:02
Friday, December 14, 1 at 12:00:00 AM GMT-04:56:02
Saturday, December 15, 1 at 12:00:00 AM GMT-04:56:02
Sunday, December 16, 1 at 12:00:00 AM GMT-04:56:02

hoursInDay
Tuesday, December 12, 2017 at 12:00:00 AM Eastern Standard Time
Tuesday, December 12, 2017 at 1:00:00 AM Eastern Standard Time
Tuesday, December 12, 2017 at 2:00:00 AM Eastern Standard Time
Tuesday, December 12, 2017 at 3:00:00 AM Eastern Standard Time
Tuesday, December 12, 2017 at 4:00:00 AM Eastern Standard Time
Tuesday, December 12, 2017 at 5:00:00 AM Eastern Standard Time
Tuesday, December 12, 2017 at 6:00:00 AM Eastern Standard Time
Tuesday, December 12, 2017 at 7:00:00 AM Eastern Standard Time
Tuesday, December 12, 2017 at 8:00:00 AM Eastern Standard Time
Tuesday, December 12, 2017 at 9:00:00 AM Eastern Standard Time
Tuesday, December 12, 2017 at 10:00:00 AM Eastern Standard Time
Tuesday, December 12, 2017 at 11:00:00 AM Eastern Standard Time
Tuesday, December 12, 2017 at 12:00:00 PM Eastern Standard Time
Tuesday, December 12, 2017 at 1:00:00 PM Eastern Standard Time
Tuesday, December 12, 2017 at 2:00:00 PM Eastern Standard Time
Tuesday, December 12, 2017 at 3:00:00 PM Eastern Standard Time
Tuesday, December 12, 2017 at 4:00:00 PM Eastern Standard Time
Tuesday, December 12, 2017 at 5:00:00 PM Eastern Standard Time
Tuesday, December 12, 2017 at 6:00:00 PM Eastern Standard Time
Tuesday, December 12, 2017 at 7:00:00 PM Eastern Standard Time
Tuesday, December 12, 2017 at 8:00:00 PM Eastern Standard Time
Tuesday, December 12, 2017 at 9:00:00 PM Eastern Standard Time
Tuesday, December 12, 2017 at 10:00:00 PM Eastern Standard Time
Tuesday, December 12, 2017 at 11:00:00 PM Eastern Standard Time

How to check consecutive weekdays in an array

A couple points:

  • Since you don't need weekends, filter them out

  • Your function is non-deterministic, since it uses the current time (Date()). The result is theoretically different for every run. I added a second parameter fromDate to make it deterministic.


func datesCheck(_ dates: [Date], fromDate: Date = Date()) -> Int {
let calendar = Calendar.current
let weekdays = dates.map { calendar.startOfDay(for: $0) }
.filter { 2...6 ~= calendar.component(.weekday, from: $0) }
let uniqueDates = Set(weekdays).sorted(by: >)

var i = 0
var lastDate = calendar.startOfDay(for: fromDate)
while i < uniqueDates.count && uniqueDates[i] == lastDate {
switch calendar.component(.weekday, from: uniqueDates[i]) {
case 2:
// When the lastDate is a Monday, the previous weekday is 3 days ago
lastDate = calendar.date(byAdding: .day, value: -3, to: lastDate)!
default:
// Otherwise, it's 1 day ago
lastDate = calendar.date(byAdding: .day, value: -1, to: lastDate)!
}
i += 1
}
return i
}

Test:

let dates = [
DateComponents(calendar: .current, year: 2017, month: 8, day: 29).date!,
DateComponents(calendar: .current, year: 2017, month: 8, day: 28).date!,
DateComponents(calendar: .current, year: 2017, month: 8, day: 25).date!,
DateComponents(calendar: .current, year: 2017, month: 8, day: 24).date!,
DateComponents(calendar: .current, year: 2017, month: 8, day: 22).date!,
DateComponents(calendar: .current, year: 2017, month: 8, day: 21).date!
]
let today = DateComponents(calendar: .current, year: 2017, month: 8, day: 29).date!
print(datesCheck(dates, fromDate: today)) // 4

The code prints 4 since the gap between the 28th and 25th is ignored according to the weekend rule.



Related Topics



Leave a reply



Submit