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

枚举2018年每月第29日返回结果异常的技术问询

解决Calendar枚举每月指定日期的异常问题

我太懂这个坑了!你遇到的问题其实是Calendar默认的日期滚动逻辑导致的:当你从1月29日调用date(byAdding: .month, value: 1, to: date)时,2018年2月没有29日,Calendar会自动回滚到当月最后一天也就是2月28日。之后再每次加一个月,就会基于2月28日得到3月28日、4月28日……自然再也拿不到29日了,所以最终只有1月29日符合预期。

解决方案1:基于当月1日计算目标日期

这种方法更可靠,先定位到当月1日,再添加28天(每个月至少有28天),然后检查这个日期是否属于当月的29日——如果是就保留,否则跳过(比如2018年2月)。

let calendar = Calendar(identifier: .gregorian)
calendar.locale = Locale(identifier: "en_US")
calendar.timeZone = TimeZone(identifier: "America/Chicago")!

var currentDateComponents = DateComponents(year: 2018, month: 1, day: 1)
var validDates: [Date] = []

for month in 1...12 {
    currentDateComponents.month = month
    // 先拿到当月1日
    guard let firstOfMonth = calendar.date(from: currentDateComponents) else { continue }
    // 添加28天,得到当月29日(如果存在的话)
    guard let targetDate = calendar.date(byAdding: .day, value: 28, to: firstOfMonth) else { continue }
    // 验证这个日期的月份是否和当前循环的月份一致(避免2月的情况)
    let targetMonth = calendar.component(.month, from: targetDate)
    if targetMonth == month {
        validDates.append(targetDate)
    }
}

print(validDates.count) // 输出11,符合预期

解决方案2:直接用DateComponents构建日期并验证

另一种思路是直接构建每个月29日的DateComponents,然后尝试转换成Date——如果转换成功,说明当月存在29日,就保留这个日期。

let calendar = Calendar(identifier: .gregorian)
calendar.locale = Locale(identifier: "en_US")
calendar.timeZone = TimeZone(identifier: "America/Chicago")!

var validDates: [Date] = []

for month in 1...12 {
    let components = DateComponents(
        year: 2018,
        month: month,
        day: 29,
        timeZone: calendar.timeZone,
        calendar: calendar
    )
    if let date = calendar.date(from: components) {
        validDates.append(date)
    }
}

print(validDates.count) // 输出11,符合预期

这两种方法都能避开Calendar自动回滚的坑,准确筛选出存在29日的月份对应的日期。

内容的提问来源于stack exchange,提问作者Jon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:48:20