Developer Developer - 2 months ago 5
iOS Question

NSDateFormatter and NSDateComponents return different values for the week number

I'm making an app that creates a timetable. You can create a new one every week of the year. When the app has finished loading, it needs to load up the current week (For example: If it's the 1st of January, week 1 needs to be shown). I use NSDateFormatter to determine what the current week is.


(I was testing this on the 9th of August 2016)

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"ww"];

int currentWeek = [[time stringFromDate:[NSDate date]] intValue];

I wanted to check if it was working so I used NSLog.

NSLog(@"%i", currentWeek);

It returned


So NSDateFormatter thinks the current week is
. So far, so good. The app needs to send a push notification to tell the user that a certain period is about to begin. So the app schedules a notification using NSDateComponents.

// Setting the notification's fire date.
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *dateComps = [[NSDateComponents alloc] init];
[dateComps setWeekday:3]; // Because it's on a Tuesday
[dateComps setWeekOfYear:currentWeek]; // 32
[dateComps setYear:2016];
[dateComps setHour:12];
[dateComps setMinute:20];
NSDate *theFireDate = [calendar dateFromComponents:dateComps];

// Creates the notification.
UILocalNotification *Alert = [[UILocalNotification alloc] init];
Alert.timeZone = [NSTimeZone defaultTimeZone];
Alert.alertBody = @"This is a message!";
Alert.fireDate = theFireDate;
[[UIApplication sharedApplication] scheduleLocalNotification:Alert];

And I also used NSLog.

NSLog(@"%@", theFireDate);

But it returned
2016-08-02 12:20:00 +0000
which is not the current date. It actually is the current date minus 7 days, or one week earlier. So does this mean that the current week is actually
instead of
, which means NSDateFormatter is wrong? Or is it actually
which means NSDateComponents is wrong. And what causes the difference between those two?


Don't use NSDateFormatter, use NSCalendar which is much more accurate.

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSInteger weekOfYear = [calendar component:NSCalendarUnitWeekOfYear fromDate:[NSDate date]];