2

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.

keegan3d
  • 10,357
  • 9
  • 53
  • 77

1 Answers1

3

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
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • Thanks, that's a nicer way of getting the number of days in a month. But still looking for a way to tell if a month every contains a leap day.`numberOfDaysIn(month: 2, of: 2020)` return 29, but 28 for 2019. I'm looking for a way to get the maximum number of days a month can have. – keegan3d Jan 07 '20 at 04:02
  • Why do you need to return 29 for years that are not leap years? Why don't you simply pass a year value that it is known to be a leap year? – Leo Dabus Jan 07 '20 at 04:06
  • For the type of calendar view I'm building, in it you pick a day, then see the entries on that day from every year. So I want to be able to include leap days and then only show the right years. I.e. Feb 28 would show every year, Feb 29 would show every 4 years. – keegan3d Jan 07 '20 at 04:12
  • Still not clear what you actually want as the result of your method. Can you provide the desired input and output. If you input day 29 what should be returned? An array with all years that contains that day? – Leo Dabus Jan 07 '20 at 04:15
  • 1
    Looking for something like `numberOfDaysIn(month: 2)` to always return 29, irregardless of what the current year is. – keegan3d Jan 07 '20 at 04:18