Swift Calendar重设同值firstWeekday后周数计算异常回退问题
问题根因
这是Foundation框架Calendar类型长期存在的实现缺陷,触发逻辑稳定可复现,和开发环境、系统版本无直接关联:
- 使用
.iso8601标识符初始化Calendar时,内部会维护两套和周计算相关的值:一套是对外暴露的公开属性值,另一套是日期计算专用的内部缓存值,初始状态下两者保持一致:firstWeekday = 2(周一为周起始日)、minimumDaysInFirstWeek = 4(首周至少包含4天,符合ISO8601标准)。 - 单独修改
minimumDaysInFirstWeek属性时,公开属性和内部计算缓存会同步更新,因此步骤1修改后周数计算结果符合预期。 - 只要对
firstWeekday执行赋值操作,无论传入的值和当前公开属性值是否完全一致,都会触发内部的参数联动逻辑:自动把计算缓存中的minimumDaysInFirstWeek重置为当前历法的默认值4,但这个重置操作不会同步更新对外公开的minimumDaysInFirstWeek属性。
这就导致步骤2出现了看似矛盾的现象:打印公开属性看到minimumDaysInFirstWeek还是1,实际周数计算用的是缓存里被重置为4的值,结果直接回退到初始状态。
规避方案
两种方案都可以彻底绕过这个问题:
- 调整属性赋值顺序:只要修改过
firstWeekday(哪怕赋的值和默认值相同),立刻重新赋值一次minimumDaysInFirstWeek,强制内部计算缓存同步为你设置的值。修正后的步骤2代码如下:
print("\n*** Step 2 修正后 ***") calendar.firstWeekday = 2 calendar.minimumDaysInFirstWeek = 1 // 新增该行,强制同步缓存值 print("firstWeekday : \(calendar.firstWeekday)") print("minimumDaysInFirstWeek : \(calendar.minimumDaysInFirstWeek)") print("weekOfMonth : \(calendar.component(.weekOfMonth, from: date!))") print("weekOfYear : \(calendar.component(.weekOfYear, from: date!))")
运行后weekOfMonth和weekOfYear都会正确返回1。
- 如果不需要修改周起始日,不要对
firstWeekday做任何重复赋值操作,哪怕值和默认值完全一致,从根源上避免触发错误的内部重置逻辑。
内容的提问来源于stack exchange,提问作者capibara
相关产品推荐
相关产品推荐

