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