为一年中第一周的日期计算一周的第一天的日期会更改月份

Calculating the date of the first day of the week for a date in the first week of the year changes the month

我需要从任意日期获取一周第一天的日期。 这段代码工作正常,但对于某些日期,我得到了一个非常奇怪的结果。一年中第一周的日期转换为上周的日期:

NSTimeInterval ti = 1420311299;
NSDate* date = [NSDate dateWithTimeIntervalSince1970:ti];

NSLog(@"%@", date); // OUTPUT: 2015-01-03 18:54:59 +0000

NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents *cmps = [calendar components:(kCFCalendarUnitWeekOfYear | kCFCalendarUnitYear) fromDate:date];

cmps.weekday = calendar.firstWeekday;

NSLog(@"%@", cmps); // OUTPUT:  Calendar Year: 2015
                    //          Week of Year: 1
                    //          Weekday: 1



NSDate* newDate = [calendar dateFromComponents:cmps];

NSLog(@"%@", newDate); // OUTPUT: 2015-12-26 22:00:00 +0000

NSCalendar class 提供了专门的方法来进行这样的计算:

NSDate *date =...;
NSDate *startOfTheWeek;
NSTimeInterval interval;
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitWeekOfMonth
                                startDate:&startOfTheWeek 
                                 interval:&interval 
                                  forDate:date];

interval 包含一周的长度。如果你不需要那个,你可以传入 NULL.

NSDate *date =...;
NSDate *startOfTheWeek;
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitWeekOfMonth 
                                startDate:&startOfTheWeek 
                                 interval:NULL
                                  forDate:date];

回答您原来的问题:周的开始和结束与年不一致。 1 月 1 日、2 日和 3 日可能是上一年的第 53 周。 12月29日、30日、31日可能是下一年的第一个星期。规则是:如果本周的周四是十二月,则该周属于旧年。如果是一月份,那一周就是新年的第一周。


每个 Mac/iOS 开发者都应该观看:WWDC 2011 视频 "Session 117 - Performing Calendar Calculations"