I need to get date for the first day of the week from any date. This code works fine, but for some dates I get a very strange result. A date from the first week of the year converts to last week's date:
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
The NSCalendar
class offers dedicated methods to do calculations like this:
NSDate *date =...;
NSDate *startOfTheWeek;
NSTimeInterval interval;
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitWeekOfMonth
startDate:&startOfTheWeek
interval:&interval
forDate:date];
interval
contains the length of the week. If you don't need that, you can just pass in NULL
.
NSDate *date =...;
NSDate *startOfTheWeek;
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitWeekOfMonth
startDate:&startOfTheWeek
interval:NULL
forDate:date];
To answer your original question: Weeks' starts and ends are not aligned with years'. The 1st, 2nd, and 3rd of January might be in the 53rd week of the previous year. 29th, 30th, 31st December might be in the 1st week of the following year. The rule is: if this week's Thursday is in December, the week belongs to the old year. If it is in January, the week is the first week of the new year.
Every Mac/iOS Developer should watch: WWDC 2011 Video "Session 117 - Performing Calendar Calculations"