Search code examples
objective-cioscocoa-touchnsdate

iOS: Compare two NSDate-s without time portion


I want to compare two dates: date1 and date2

2011-06-06 12:59:48.994 Project[419:707] firstDate:2011-06-06 10:59:21 +0000
2011-06-06 12:59:49.004 Project[419:707] selectedData:2011-06-06 10:59:17 +0000

but these dates have different time and when I use NSOrderedSame it don't work fine, how can I solve?

my code:

NSDate *firstDate = [[appDelegate.project objectAtIndex:i]objectAtIndex:3];
NSDate *secondDate = [[appDelegate.project objectAtIndex:i]objectAtIndex:4];

NSCalendar *calendar = [NSCalendar currentCalendar];
NSInteger comps = (NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit);

NSDateComponents *date1Components = [calendar components:comps 
                                                            fromDate:firstDate];
NSDateComponents *date2Components = [calendar components:comps 
                                                            fromDate:secondDate];
NSDateComponents *date3Components = [calendar components:comps fromDate:appDelegate.selectedDate];

NSLog(@"firstDate:%@", [date1Components date]);
NSLog(@"secondDate:%@", [date2Components date]);
NSLog(@"selectedData:%@", [date3Components date]);

NSComparisonResult compareStart = [[date1Components date] compare: [date3Components date]]; 
NSComparisonResult compareEnd = [[date2Components date] compare: [date3Components date]]; 

if ((compareStart == NSOrderedAscending || compareStart == NSOrderedSame)
     && (compareEnd == NSOrderedDescending || compareEnd == NSOrderedSame))

{
    NSLog(@"inside");

Then I want to compare my dates and entry inside the "if" when date1 <= selectedDate <= date2; now I understand because I have a warning: I should add this "[date1Components date]" and it work; the problem is that I have in the NSLog null values, why??


Solution

  • NSCalendar *calendar = [NSCalendar currentCalendar];
    NSInteger comps = (NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear);
    
    NSDateComponents *date1Components = [calendar components:comps 
                                                    fromDate: date1];
    NSDateComponents *date2Components = [calendar components:comps 
                                                    fromDate: date2];
    
    date1 = [calendar dateFromComponents:date1Components];
    date2 = [calendar dateFromComponents:date2Components];
    
    NSComparisonResult result = [date1 compare:date2];
    if (result == NSOrderedAscending) {
    } else if (result == NSOrderedDescending) {
    }  else {
        //the same
    }
    

    There is another handy method to create for a given date the date that represents the start of a given unit: [aCalendar rangeOfUnit:startDate:interval:forDate:]
    To illustrate how this method works, see this code, that easily creates the date for the beginning of the day, week, month and year for a given date (here: now).

    NSDate *now = [NSDate date];
    NSDate *startOfToday = nil;
    NSDate *startOfThisWeek = nil;
    NSDate *startOfThisMonth = nil;
    NSDate *startOfThisYear = nil;
    [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&startOfToday interval:NULL forDate:now];
    [[NSCalendar currentCalendar] rangeOfUnit:NSWeekCalendarUnit startDate:&startOfThisWeek interval:NULL forDate:now];
    [[NSCalendar currentCalendar] rangeOfUnit:NSMonthCalendarUnit startDate:&startOfThisMonth interval:NULL forDate:now];
    [[NSCalendar currentCalendar] rangeOfUnit:NSYearCalendarUnit startDate:&startOfThisYear interval:NULL forDate:now];
    
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateStyle:NSDateFormatterFullStyle];
    [formatter setTimeStyle:NSDateFormatterFullStyle];
    
    NSLog(@"%@", [formatter stringFromDate:now]);
    NSLog(@"%@", [formatter stringFromDate:startOfToday]);
    NSLog(@"%@", [formatter stringFromDate:startOfThisWeek]);
    NSLog(@"%@", [formatter stringFromDate:startOfThisMonth]);
    NSLog(@"%@", [formatter stringFromDate:startOfThisYear]);
    

    result:

    Thursday, July 12, 2012, 4:36:07 PM Central European Summer Time 
    Thursday, July 12, 2012, 12:00:00 AM Central European Summer Time 
    Sunday, July 8, 2012, 12:00:00 AM Central European Summer Time 
    Sunday, July 1, 2012, 12:00:00 AM Central European Summer Time 
    Sunday, January 1, 2012, 12:00:00 AM Central European Standard Time
    

    this allows us to shorten the first code to:

    [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&date1 interval:NULL forDate:date1];
    [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&date2 interval:NULL forDate:date2];
    
    NSComparisonResult result = [date1 compare:date2];
    if (result == NSOrderedAscending) {
    } else if (result == NSOrderedDescending) {
    }  else {
        //the same
    }
    

    Note, that in this code, date1 and date2 will be overwritten. Alternatively you can pass in a reference to another NSDate pointer for startDate as shown in the code above, where now stays untouched.