Search code examples
iphonensdatecomponent

NSDateComponents - day method returning wrong day


I can't seem to figure out why the day doesn't change when I get to the 6th of November, 2011. All I'm doing is iterating through the days. Any help would be appreciated. Here is my code:

NSCalendar* calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents* comp = [[NSDateComponents alloc] init];

[comp setDay:2];
[comp setMonth:11];
[comp setYear:2011];

NSDate* date = [calendar dateFromComponents:comp];

for (int i = 0; i < 7; i++) {
    NSDate* d = [date dateByAddingTimeInterval:((3600 * 24) * i)];
    NSDateComponents* dComponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:d];

    int day = [dComponents day];
    NSLog(@"\nDate: %@\nDay: %i", [d description], day);
}

This is my output:

Date: 2011-11-02 06:00:00 +0000
Day: 2

Date: 2011-11-03 06:00:00 +0000
Day: 3

Date: 2011-11-04 06:00:00 +0000
Day: 4

Date: 2011-11-05 06:00:00 +0000
Day: 5

Date: 2011-11-06 06:00:00 +0000
Day: 6

Date: 2011-11-07 06:00:00 +0000
Day: 6

Date: 2011-11-08 06:00:00 +0000
Day: 7

Thanks!


Solution

  • November, 6 is a day when time changed due to the Day Saving Time so that day actually lasts 25 hours and incorrect result is probably comes from that (in general adding time intervals to a date is unreliable because of calendar irregularities and bahaviour may depend on many parameters: current calendar, time zone, locale settings etc).

    The more correct way to iterate through days (per wwdc11 video "Performing Calendar Calculations"(iTunes link)) is to add appropriate number of date components to a starting date on each iteration:

    ...
    NSDateComponents *addComponents = [[NSDateComponents alloc] init];
    for (int i = 0; i < 7; i++) {
        [addComponents setDay: i];
        NSDate* d = [calendar dateByAddingComponents:addComponents toDate:date options:0];        
         NSDateComponents* dComponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:d];
    
         int day = [dComponents day];
         NSLog(@"\nDate: %@\nDay: %i", [d description], day);
    }