0

I found this old post regarding how to find the next Monday, Tuesday... etc. This is helpful, but what if we want to find next weekday or weekend? The next weekend might be Saturday, or it might be Sunday, so now what should I do to let the code decide for us? (That goes similarly to find the next weekday, which has 5 choices based on the current date).

Any help would work. Is there a way to modify the existing extension I mentioned before in the old post?

Jack Stark
  • 57
  • 7
  • Use `DateComponents`'s `weekday` property. – El Tomato Oct 31 '21 at 09:45
  • 2
    You can use [nextDate(after:...)](https://developer.apple.com/documentation/foundation/calendar/2293473-nextdate) or [nextWeekend(startingAfter:...)](https://developer.apple.com/documentation/foundation/calendar/2293501-nextweekend). – Joakim Danielson Oct 31 '21 at 10:16
  • Would you mind giving me an example of `nextWeekend(startingAfter)` function? I couldn't find helpful resources and Apple documentation doesn't provide an example. Say if I have `let date = Date()` how to get the `date`'s next available weekend (Saturday or Sunday whoever is closer). And how to get `date`'s the next available weekday (Mon, Tue, Wed, Thu, Fri whoever is closer)? – Jack Stark Nov 01 '21 at 00:30

3 Answers3

1

Finding the date for the next weekend is simple.

let now = Date()
if let timeInterval = cal.nextWeekend(startingAfter: now, direction: .forward) {
    let startDate = timeInterval.start
    let endDate = timeInterval.end
    print(startDate, endDate)
}

nextWeekend(startingAfter:direction:) does not return a specific Date object. It returns a DateInterval object, instead.

Finding the next date for any of week days is a challenge. That's because it can be Monday, Tuesday, Wednesday, Thursday or Friday. The following is how to find the next Monday.

let cal = Calendar.current
var comps = DateComponents()
comps.weekday = 2
let now = Date()
if let nextMonday = cal.nextDate(after: now, matching: comps, matchingPolicy: .nextTimePreservingSmallerComponents) {
    print(nextMonday)
}

, where 2 is for Monday.

El Tomato
  • 6,479
  • 6
  • 46
  • 75
  • 1
    Thank you this is very informative, to find the next weekday, I now would generally add 24 hours, except it's Friday, in that case I find the next Monday. – Jack Stark Nov 02 '21 at 06:53
  • @JackStark: naïvely adding 24 hours will fail when you cross Daylight Saving Time boundaries or added leap seconds. Better to use `Calendar` and `DateComponents` to derive such dates. – Ben Kennedy Oct 26 '22 at 23:58
0

You might as well leverage on enumerateDates(startingAfter:matchingPolicy:using) Calendar's method:

extension Calendar {
    enum KindOfDay {
        case weekend
        case weekday
        
    }
    
    func next(_ kind: KindOfDay) -> Date? {
        let now = Date.init(timeIntervalSinceNow: 0)
        let dc = DateComponents(hour: 0, minute: 0, second: 0)
        
        var result: Date?
        enumerateDates(startingAfter: now, matching: dc, matchingPolicy: .nextTime, using: { candidate, _, stop in
            guard
                let candidate = candidate
            else {
                stop = true
                return
            }
            
            let isWeekend = isDateInWeekend(candidate)
            stop = kind == .weekend ? isWeekend : !isWeekend
            result = stop ? candidate : nil
        })
        
        return result
    }
    
}
valeCocoa
  • 344
  • 1
  • 8
0

Leveraging Calendar’s isDateInWeekend(), finding the next weekday following a given date is straightforward:

func nextWeekday(after date: Date,
                 in calendar: Calendar) -> Date {
    var components = calendar.dateComponents([.year, .month, .day],
                                             from: date)
    var nextDate: Date!
    repeat {
        components.day! += 1
        nextDate = calendar.date(from: components)
    } while calendar.isDateInWeekend(nextDate)
    
    return nextDate
}
let calendar = Calendar.current
let date = calendar.date(from: DateComponents(year: 2022, month: 10, day: 28))!
// Fri 2022-10-28 07:00:00 UTC
let nextDate = nextWeekday(after: date, in: calendar)
// Mon 2022-10-31 07:00:00 UTC
Ben Kennedy
  • 288
  • 2
  • 8