Search code examples
objective-cnsdatenscalendar

Result of component properties, when not queried from calendar components:fromDate:


If i call

NSDateComponents * components = [calendar components:(NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:self];

and than ask, lets say for the

components.minute

will it guaranteed to give me 0 ?

i done smth. like this, however to be sure it works 100%, the above condition needs to be med also for next versions of iOS

- (BOOL)isInTheSameComponents:(NSUInteger)components withDate:(NSDate *)date {

    NSCalendar *calendar = [NSCalendar currentCalendar];

    NSDateComponents *components1 = [calendar components:components fromDate:self];
    NSDateComponents *components2 = [calendar components:components fromDate:date];

    return ((components1.month == components2.month) && (components1.year == components2.year) && (components1.day == components2.day) && (components1.hour == components2.hour) && (components1.minute == components2.minute));

}

- (BOOL)isInTheSameMonthAndYearWithDate:(NSDate *)date {

    return [self isInTheSameComponents:(NSMonthCalendarUnit | NSYearCalendarUnit) withDate:date];
}

Solution

  • In order to avoid this (possibly undefined) behaviour, just test the components you are extracting:

    - (BOOL)isInTheSameComponents:(NSUInteger)components withDate:(NSDate *)date {
    
        NSCalendar *calendar = [NSCalendar currentCalendar];
    
        NSDateComponents *components1 = [calendar components:components fromDate:self];
        NSDateComponents *components2 = [calendar components:components fromDate:date];
    
        if ((components & NSYearCalendarUnit) != 0 && components1.year != components2.year)
            return NO;
        if ((components & NSMonthCalendarUnit) != 0 && components1.month != components2.month)
            return NO;
        if ((components & NSDayCalendarUnit) != 0 && components1.day != components2.day)
            return NO;
        if ((components & NSHourCalendarUnit) != 0 && components1.hour != components2.hour)
            return NO;
        if ((components & NSMinuteCalendarUnit) != 0 && components1.minute != components2.minute)
            return NO;
        // and any other components you might use
        return YES;
    }
    

    I would suggest a better name for this method would be:

    - (BOOL)isEqualToComponents:(NSUInteger)components inDate:(NSDate *)date
    {
       ...
    }
    

    (I assume this is an NSDate category)