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

Swift按月份过滤日期数组返回错误结果的原因排查

问题原因分析

你的代码出现不符合预期的过滤结果,核心原因是处理日期时使用了两个不一致的Calendar实例:

  1. 在Date的自定义初始化方法中,你用Calendar.current(系统默认日历,包含本地时区)生成日期;
  2. 在month计算属性中,你用了单独创建的cal实例(ISO8601日历,默认时区为UTC)解析月份。

同一个UTC格式的日期,在不同时区的日历下会被解析为不同的本地日期。比如:

  • 若你的本地时区是UTC+5,Date(month:9, day:30, year:2023)生成的本地时间是2023-09-30 00:00:00,对应的UTC时间是2023-09-29 19:00:00;
  • 当用UTC时区的ISO8601日历解析这个UTC时间时,得到的月份会和本地日历解析结果产生偏差,导致原本属于9月的日期被错误识别为10月,最终被过滤到结果数组中。

另外,代码里cal作为全局变量被Date的extension直接引用,耦合性高,容易引发意外问题。

修复方案

统一使用同一个Calendar实例来创建和解析日期,两种可选方案:

方案1:统一使用系统默认日历

extension Date {
    init(month: Int, day: Int, year: Int) {
        let cal = Calendar.current
        var dateComponents = DateComponents()
        dateComponents.month = month
        dateComponents.day = day
        dateComponents.year = year
        self = cal.date(from: dateComponents) ?? Date()
    }
    
    var month: Int {
        let cal = Calendar.current
        return cal.component(.month, from: self)
    }
}

let sampleArr = [Date(month: 09, day: 30, year: 2023), Date(month: 10, day: 1, year: 2023)]
let filterArr = sampleArr.filter{ $0.month == 10 }
print(filterArr)

方案2:统一使用ISO8601日历

extension Date {
    private static let isoCalendar = Calendar(identifier: .iso8601)
    
    init(month: Int, day: Int, year: Int) {
        var dateComponents = DateComponents()
        dateComponents.month = month
        dateComponents.day = day
        dateComponents.year = year
        self = Date.isoCalendar.date(from: dateComponents) ?? Date()
    }
    
    var month: Int {
        return Date.isoCalendar.component(.month, from: self)
    }
}

let sampleArr = [Date(month: 09, day: 30, year: 2023), Date(month: 10, day: 1, year: 2023)]
let filterArr = sampleArr.filter{ $0.month == 10 }
print(filterArr)

统一日历实例后,创建日期和解析月份的规则完全一致,过滤结果就能符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 16:58:14