简体   繁体   中英

Get the dates of all tuesdays between two dates in Swift

What I need is to get all the dates of an specefic day between two dates.

For example.

Day: Tuesday Beginning date: september 21 2020 End date: february 15 2021

Output: dates of every tuesday among those dates

I'm new in Date operations so I don't quite know how I can achieve this.

Does anyone know? Thanks

You can use calendar method nextDate(after:, matching:, matchingPolicy, repeatedTimePolicy:, direction:) inside a while loop and add a condition to check if the resulting date is less or equal to the end date:

func nextDate(after date: Date, matching components: DateComponents, matchingPolicy: MatchingPolicy, repeatedTimePolicy: RepeatedTimePolicy = .first, direction: SearchDirection = .forward) -> Date?

var start = DateComponents(calendar: .current, year: 2020, month: 9, day: 21).date!
let end = DateComponents(calendar: .current, year: 2021, month: 2, day: 15).date!

var dates: [Date] = []
while let date = Calendar.current.nextDate(after: start, matching: DateComponents(weekday: 3), matchingPolicy: .strict), date <= end {
    dates.append(date)
    start = date
}

print(dates) 

You can also extend DateInterval and create a custom method to return all dates between start and end dates that matches the date components:

extension DateInterval {
    func dates(matching components: DateComponents) -> [Date] {
        var start = self.start
        var dates: [Date] = []
        while let date = Calendar.current.nextDate(after: start, matching: components, matchingPolicy: .strict), date <= end {
            dates.append(date)
            start = date
        }
        return dates
    }
}

Usage:

let start = DateComponents(calendar: .current, year: 2020, month: 9, day: 21).date!
let end = DateComponents(calendar: .current, year: 2021, month: 2, day: 15).date!
let dateInterval: DateInterval = .init(start: start, end: end)
let tuesdays = dateInterval.dates(matching: .init(weekday: 3))
print(tuesdays) 

This will print

[2020-09-22 03:00:00 +0000, 2020-09-29 03:00:00 +0000, 2020-10-06 03:00:00 +0000, 2020-10-13 03:00:00 +0000, 2020-10-20 03:00:00 +0000, 2020-10-27 03:00:00 +0000, 2020-11-03 03:00:00 +0000, 2020-11-10 03:00:00 +0000, 2020-11-17 03:00:00 +0000, 2020-11-24 03:00:00 +0000, 2020-12-01 03:00:00 +0000, 2020-12-08 03:00:00 +0000, 2020-12-15 03:00:00 +0000, 2020-12-22 03:00:00 +0000, 2020-12-29 03:00:00 +0000, 2021-01-05 03:00:00 +0000, 2021-01-12 03:00:00 +0000, 2021-01-19 03:00:00 +0000, 2021-01-26 03:00:00 +0000, 2021-02-02 03:00:00 +0000, 2021-02-09 03:00:00 +0000]

A lot depends on what you have to start with. Do you have the values as Date or String ?

I prefer to have Date , but for testing, I started with String ...

let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd"
guard let startDate = formatter.date(from: "2020/09/21"), let endDate = formatter.date(from: "2021/02/15") else { return [] }

Of course, your inputs may be in a different format so you'll need to compensate for this.

Next, we need to find the next Tuesday from the start date

var calendar = Calendar.current
calendar.firstWeekday = 2 // Make Monday the starting point, don't know if I need to compensate for this, but not taking any risks
var components = DateComponents()
components.weekday = 3 // Look for Tuesdays
guard var date = calendar.nextDate(after: startDate, matching: components, matchingPolicy: .nextTime) else { return [] }

Next, we simply want to increment the date by 7 days so we can jump to the next Tuesday

var datesOfInterest: [Date] = []

while date < endDate {
    datesOfInterest.append(date)
    guard date = calendar.date(byAdding: .day, value: 7, to: date) else { 
        // You might want to consider this to be an error, but I'm
        // just going for brevity
        return [] 
    }
}

return datesOfInterest

Obviously, this assumes you have a function which returns an array of Date values.

And just for testing...

let test = DateFormatter()
test.dateFormat = "eeee dd MM yyyy"

print(datesOfInterest.map { test.string(from: $0) }.joined(separator: ", "))

which outputted...

Tuesday 22 09 2020, Tuesday 29 09 2020, Tuesday 06 10 2020, Tuesday 13 10 2020, Tuesday 20 10 2020, Tuesday 27 10 2020, Tuesday 03 11 2020, Tuesday 10 11 2020, Tuesday 17 11 2020, Tuesday 24 11 2020, Tuesday 01 12 2020, Tuesday 08 12 2020, Tuesday 15 12 2020, Tuesday 22 12 2020, Tuesday 29 12 2020, Tuesday 05 01 2021, Tuesday 12 01 2021, Tuesday 19 01 2021, Tuesday 26 01 2021, Tuesday 02 02 2021, Tuesday 09 02 2021

in my testing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM