Objective-C获取上周一日期代码报错排查:2018年1月5日未返回1月1日
问题排查与修复方案
嘿,我来帮你搞定这个日期计算的bug!你的代码在处理2018年1月5日时返回了不符合预期的日期,核心原因是依赖weekOfYear和year组合构造日期的方式不可靠,不同地区的日历系统对“年度第一周”的定义存在差异,导致结果跑偏了。
错误原因拆解
2018年1月1日本身就是周一,但你的代码里仅通过weekOfYear=1、year=2018和weekday=2来构造日期,既没有明确初始化calendar实例(你贴的代码里直接调用了[calendar components:]但未定义变量),也没有统一日历的周起始规则。部分日历(比如遵循ISO 8601标准的)会把包含当年第一个周四的周算作第一周,这就可能导致系统误判2018年第一周的周一为2017年12月31日,最终出现你看到的异常结果。
更靠谱的修复方案
与其靠周数拼接日期,不如直接从目标日期往前推算到最近的周一,这种方法不受日历周定义的影响,逻辑更清晰,结果也更准确:
// 明确初始化日历实例,并统一周起始为周一(避免不同地区默认设置的干扰) NSCalendar *calendar = [NSCalendar currentCalendar]; calendar.firstWeekday = 2; // 1=周日,2=周一,以此类推 NSDate *targetDate = [NSDate date]; // 这里替换成你要处理的日期,比如2018-01-05 NSDateComponents *weekdayComponents = [calendar components:NSWeekdayCalendarUnit fromDate:targetDate]; // 计算需要回溯的天数:如果当天是周一,回溯0天;否则回溯(weekday - 起始周几)天 NSInteger daysToBacktrack = weekdayComponents.weekday - calendar.firstWeekday; // 处理极端跨周情况(比如日历默认周日为起始时的兼容,我们已设周一为起始,保留更稳妥) if (daysToBacktrack < 0) { daysToBacktrack += 7; } // 生成上周一的日期 NSDateComponents *subtractComponents = [[NSDateComponents alloc] initWithDay:-daysToBacktrack]; NSDate *lastMonday = [calendar dateByAddingComponents:subtractComponents toDate:targetDate options:0]; NSLog(@"last monday is : %@", lastMonday);
代码逻辑说明
- 先初始化日历并设置
firstWeekday=2,确保一周从周一开始,避免不同地区默认日历(比如部分地区以周日为一周第一天)的干扰。 - 获取目标日期的星期数,计算需要往回退的天数:比如2018年1月5日是周五,
weekday为6,6-2=4,往回退4天就是1月1日(周一)。 - 用
dateByAddingComponents直接调整日期,得到准确的上周一。
用这个方法处理2018年1月5日时,会正确返回2018-01-01,完全符合你的预期。
内容的提问来源于stack exchange,提问作者Hemanathan




