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

设置Date的weekday属性返回错误结果:周一指向下周日期

关于Calendar.date(bySetting:weekday:)的日期偏移问题

问题场景

执行以下Swift代码:

print(Date().description(with: .current))
print("--")
print(Calendar.current.date(bySetting: .weekday, value: 2, of: Date())?.description(with: .current))
print(Calendar.current.date(bySetting: .weekday, value: 3, of: Date())?.description(with: .current))
print(Calendar.current.date(bySetting: .weekday, value: 4, of: Date())?.description(with: .current))
print(Calendar.current.date(bySetting: .weekday, value: 5, of: Date())?.description(with: .current))
print(Calendar.current.date(bySetting: .weekday, value: 6, of: Date())?.description(with: .current))
print(Calendar.current.date(bySetting: .weekday, value: 7, of: Date())?.description(with: .current))
print(Calendar.current.date(bySetting: .weekday, value: 1, of: Date())?.description(with: .current))

输出结果:

Tuesday, 3 January 2023 at 02:07:35 Eastern European Standard Time
--
Monday, 9 January 2023 at 00:00:00 Eastern European Standard Time
Tuesday, 3 January 2023 at 02:07:35 Eastern European Standard Time
Wednesday, 4 January 2023 at 00:00:00 Eastern European Standard Time
Thursday, 5 January 2023 at 00:00:00 Eastern European Standard Time
Friday, 6 January 2023 at 00:00:00 Eastern European Standard Time
Saturday, 7 January 2023 at 00:00:00 Eastern European Standard Time
Sunday, 8 January 2023 at 00:00:00 Eastern European Standard Time

疑问:为何设置weekday为2时返回的是1月9日(下周)的周一,而非预期的1月2日?另外,若尝试设置weekOfYear属性,其他日期均正常,但周一的日期会变为2024年的日期。

原因分析

这是因为Calendar.current.date(bySetting:of:)的默认行为是从给定日期开始,向后查找第一个匹配指定组件值的日期。如果当前日期的weekday值大于目标值,方法就会跳过当前周期,直接匹配下一个周期的目标日期。

在测试场景中,当前日期是2023年1月3日(周二,weekday为3),目标weekday是2(周一),由于3>2,方法会向后寻找下一个周一,也就是1月9日,而非往前回溯1月2日。

针对weekOfYear的问题,本质也是相同的匹配逻辑:当当前日期的周内已过周一,直接设置weekOfYear配合weekday时,默认策略会向后跳转到下一年的对应周。

解决方案

要获取当前所在周的目标工作日,可通过以下两种方式实现:

方式1:指定匹配策略

使用date(bySetting:value:of:matchingPolicy:)方法,指定matchingPolicy参数来控制查找逻辑:

// 获取当前日期所在周的周一(优先取本周,不存在则向后找)
let thisWeekMonday = Calendar.current.date(
    bySetting: .weekday,
    value: 2,
    of: Date(),
    matchingPolicy: .nextOrSame
)

常用的匹配策略:

  • .nextOrSame:优先匹配当前日期或之后的第一个目标值
  • .previousOrSame:优先匹配当前日期或之前的第一个目标值
  • .strict:仅当当前日期完全匹配时返回,否则返回nil

方式2:构造日期组件

通过提取当前日期的年周信息,再指定weekday来构造目标日期:

var components = Calendar.current.dateComponents([.yearForWeekOfYear, .weekOfYear], from: Date())
components.weekday = 2 // 指定周一
let thisWeekMonday = Calendar.current.date(from: components)

这种方式能确保获取的是当前周的周一,不会跨到其他周。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 10:50:26