In Swift, how can I get the "last Sunday of a month before the current date"?

I want to find the "last Sunday of a month before the current date" in Swift, but using the Calendar nextDate function doesn't work (always returns nil).

var calendar: Calendar = Calendar(identifier: .gregorian)
calendar.timeZone = .gmt

let lastSundayDateComponents: DateComponents = DateComponents(
    weekday: 1,
    weekdayOrdinal: -1
)

let previousLastSundayDate: Date? = calendar.nextDate(
    after: Date.now,
    matching: lastSundayDateComponents,
    matchingPolicy: .nextTime,
    repeatedTimePolicy: .first,
    direction: .backward
)

print(previousLastSundayDate ?? "Not found") // "Not found"

If I use a positive weekdayOrdinal, it's working normally and the same nextDate method provides the correct date.

let firstSundayDateComponents: DateComponents = DateComponents(
    weekday: 1,
    weekdayOrdinal: 1
)

When I check if the date components can provide a valid date for the given calendar, it returns false...

let lastSundayInNovember2023DateComponents: DateComponents = DateComponents(
    year: 2023,
    month: 11,
    weekday: 1,
    weekdayOrdinal: -1
)
            
// THIS RETURNS FALSE
let isValid: Bool = lastSundayInNovember2023DateComponents.isValidDate(in: calendar)
print(isValid) // false

... even if the correct date can be created.

let lastSundayInNovember2023: Date = calendar.date(from: lastSundayInNovember2023DateComponents)!
print(lastSundayInNovember2023) // 2023-11-26 00:00:00 +0000

Is that a bug in Foundation?

I did not test if there's a bug.

But to get the result I would:

  • get the date of 1/1 of following month
  • step backward 1 day
  • teint read shay day it is
  • and compute backward to get the last Sunday.

Hope that's useful.

If I use a positive weekdayOrdinal, it's working normally and the same nextDate(…) method provides the correct date.

I’ve never seen anyone use negative values for weekdayOrdinal. Is that documented somewhere?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

In Swift, how can I get the "last Sunday of a month before the current date"?
 
 
Q