You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中获取非公历历法一年月份数的实现难题

解决非公历历法中获取指定年份月份数的问题

问题描述

想要获取非公历(如希伯来历)指定年份的月份数量,比如希伯来历5784年有13个月,5783年为12个月。但实现的Calendar扩展方法monthRange始终返回1..<14,无法正确返回目标年份的实际月份数;而逻辑类似的dayRange方法在公历、农历中都能正常返回对应月份的天数范围。

原实现的monthRange代码:

public extension Calendar {
    
    /// The range of months for a given year in the calendar
    func monthRange(year: Int) -> Range<Int> {
        let components  = DateComponents(calendar:  self,
                                         year:      year,
                                         month:     1,  //  I assume 1 is always valid
                                         day:       1)  //  I assume 1 is always valid
        let date        = self.date(from: components)!
        let monthRange  = self.range(of: .month, in: .year, for: date)!
        return monthRange
    }
}

问题原因

range(of: .month, in: .year, for: date)方法返回的是该历法支持的月份通用范围,而非传入日期所在年份的实际月份数。以希伯来历为例,该历法本身支持12或13个月的年份,所以这个方法会直接返回最大可能的范围1..<14,不会针对具体年份做适配。

而dayRange方法能正常工作,是因为range(of: .day, in: .month, for: date)是针对指定月份的实际天数范围,每个月份的天数是确定的,因此能返回正确结果。

解决方案

通过获取指定年份的最后一天,提取该日期所在的月份数,以此确定年份的实际月份总数。修改后的扩展方法如下:

public extension Calendar {
    /// 获取指定年份的月份范围(适配非公历历法的闰月情况)
    func monthRange(year: Int) -> Range<Int>? {
        // 构造目标年份的第一天
        guard let startDate = date(from: DateComponents(calendar: self, year: year, month: 1, day: 1)) else {
            return nil
        }
        
        // 构造下一年第一天,再往前推1天得到目标年份的最后一天
        guard let nextYearStart = date(from: DateComponents(calendar: self, year: year + 1, month: 1, day: 1)) else {
            return nil
        }
        let endDate = date(byAdding: .day, value: -1, to: nextYearStart)!
        
        // 获取最后一天所在的月份,即为该年份的总月份数
        let endMonth = component(.month, from: endDate)
        return 1..<(endMonth + 1)
    }
}

测试示例

以希伯来历为例验证:

let hebrewCalendar = Calendar(identifier: .hebrew)
print(hebrewCalendar.monthRange(year: 5783)) // 输出 1..<13
print(hebrewCalendar.monthRange(year: 5784)) // 输出 1..<14

内容的提问来源于stack exchange,提问作者AirXygène

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 06:32:48