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

Calendar.current.component(.year)返回4而非2022的原因排查求助

年份选择列表显示异常问题排查

问题背景

我们的应用内有一个年份选择页面,列表包含1900至2022的所有年份。部分用户反馈完全看不到该列表,我们无法复现问题,因此添加了非致命错误上报至Crashlytics,当列表显示的初始条件不满足时触发。

相关代码

private lazy var currentYear: Int = {
    Calendar.current.component(.year, from: Date())
}()

private lazy var yearsArray: [String] = {
    if currentYear < 1900 {
        assertionFailure()
        NSError(domain: "OTP_YEAR", code: 1, userInfo: [NSLocalizedDescriptionKey: "CurrentYear < 1900. value: \(currentYear), Date: \(Date())"])
            .reportToExternalServices()
        return []
    }
    let result = (1900 ... currentYear).map { String($0) }
    if result.isEmpty {
        assertionFailure()
        NSError(domain: "OTP_YEAR", code: 2, userInfo: [NSLocalizedDescriptionKey: "Empty years array. currentYear: \(currentYear), Date: \(Date())"])
            .reportToExternalServices()
    }
    if result.contains(where: { $0.trimWhiteSpacesAndNewLine().isEmpty }) {
        assertionFailure()
        NSError(domain: "OTP_YEAR", code: 3, userInfo: [NSLocalizedDescriptionKey: "Years array contains empty strings. currentYear: \(currentYear), Date: \(Date()), Array: \(result)"])
            .reportToExternalServices()
    }
    return result
}()

上报错误日志

nserror-code: 1
nserror-domain: OTP_YEAR
NSLocalizedDescription: CurrentYear < 1900. value: 4, Date: 2022-07-11 12:59:00 +0000

该问题发生在两位使用iPhone 13、iOS 15.5的用户身上。日志显示标准年份提取方法Calendar.current.component(.year, from: Date())返回4而非当前公元年份2022,我们无法在测试设备上复现此问题,请问可能的原因是什么?

可能的原因分析

  • 用户设备设置了日本和历(Japanese Calendar):这是最匹配日志特征的原因。当用户将设备日历系统切换为日本和历时,Calendar.current会自动切换为JapaneseCalendar实例。此时调用component(.year, from: Date())返回的是当前纪元(令和)内的年份——2022年对应令和4年,因此返回整数4,而非公元纪年的2022。该值触发了currentYear < 1900的判断条件,导致返回空数组,用户看不到年份列表。
  • 系统日历框架临时异常:iOS 15.5存在特定场景下日历年份提取错误的小概率bug,但两位用户同时出现该问题的可能性极低。
  • 第三方代码篡改全局日历设置:如果应用集成的第三方框架修改了Calendar.current的全局配置,也可能导致此问题,但相比用户手动修改日历设置的概率要低很多。

修复建议

如果业务逻辑要求始终获取公元纪年的年份,应该明确使用公历(Gregorian Calendar),避免依赖用户设备的默认日历设置,修改代码如下:

private lazy var currentYear: Int = {
    let gregorianCalendar = Calendar(identifier: .gregorian)
    return gregorianCalendar.component(.year, from: Date())
}()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 07:54:22