keegan3d
keegan3d

Reputation: 11305

Swift Date: How to tell if a month can have a leap day?

I'm building a calendar view that I want to be agnostic of the year, just list all the possible dates that can occur in a month. I.e. to show the maximum number of days in a calendar, like February 29th. From this answer, I know there are other calendar systems that also have leap days, so I'm curious how I might be able to tell if a calendar has a leap day, regardless of the calendar system or year. Any help would be greatly appreciated! Here is what I have currently to get the number of days in a month:

func days(in month: Int) -> Int {
    let components = DateComponents(month: month+1, day: -1)
    let lastDay = Calendar.current.date(from: components)!
    return Calendar.current.dateComponents([.day], from: lastDay).day!+1
}

This works great, but is based on the current year, which may not be a leap year.

I've seen isLeapMonth but this doesn't seem to work to query in the same way as .day.

Upvotes: 3

Views: 2002

Answers (1)

Leo Dabus
Leo Dabus

Reputation: 236420

edit/update:

You can get the next leap year for the current calendar and check the maximum number of days in month, maybe something like this:

extension Date {

    var year: Int { Calendar.current.component(.year, from: self) }

    var isLeapYear: Bool { Calendar.current.range(of: .day, in: .year, for: self)!.count == 366 }

    // find the leap year
    static var leapYear: Int {
        var year = Date().year
        while DateComponents(calendar: .current, year: year).date?.isLeapYear == false {
            year += 1
        }
        return year
    }
}

Date.leapYear  // 2020

func maximumNumberOfDays(in month: Int) -> Int? {
    Calendar.current.range(of: .day,
                           in: .month,
                           for: DateComponents(calendar: .current,
                                               year: Date.leapYear,
                                               month: month).date!)?.count
}

maximumNumberOfDays(in: 2)  // 29

Upvotes: 3

Related Questions