Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing two NSDates and ignoring the time component

What is the most efficient/recommended way of comparing two NSDates? I would like to be able to see if both dates are on the same day, irrespective of the time and have started writing some code that uses the timeIntervalSinceDate: method within the NSDate class and gets the integer of this value divided by the number of seconds in a day. This seems long winded and I feel like I am missing something obvious.

The code I am trying to fix is:

if (!([key compare:todaysDate] == NSOrderedDescending))
{
    todaysDateSection = [eventSectionsArray count] - 1;
}

where key and todaysDate are NSDate objects and todaysDate is creating using:

NSDate *todaysDate = [[NSDate alloc] init];

Regards

Dave

like image 895
Magic Bullet Dave Avatar asked Dec 06 '09 09:12

Magic Bullet Dave


People also ask

How do I compare NSDate?

We can also use the earlierDate: and laterDate: methods of the NSDate class: NSDate *earlierDate = [date1 earlierDate:date2];//Returns the earlier of 2 dates. Here earlierDate will equal date2. NSDate *laterDate = [date1 laterDate:date2];//Returns the later of 2 dates.

Is date equatable Swift?

Swift's Date struct conforms to both Equatable and Comparable , which means you check two dates for equality and compare them to see which is earlier.


3 Answers

I'm surprised that no other answers have this option for getting the "beginning of day" date for the objects:

[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date1 interval:NULL forDate:date1];
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date2 interval:NULL forDate:date2];

Which sets date1 and date2 to the beginning of their respective days. If they are equal, they are on the same day.

Or this option:

NSUInteger day1 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit inUnit: forDate:date1];
NSUInteger day2 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitEra forDate:date2];

Which sets day1 and day2 to somewhat arbitrary values that can be compared. If they are equal, they are on the same day.

like image 57
Ed Marty Avatar answered Oct 31 '22 21:10

Ed Marty


You set the time in the date to 00:00:00 before doing the comparison:

unsigned int flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay;
NSCalendar* calendar = [NSCalendar currentCalendar];

NSDateComponents* components = [calendar components:flags fromDate:date];

NSDate* dateOnly = [calendar dateFromComponents:components];

// ... necessary cleanup

Then you can compare the date values. See the overview in reference documentation.

like image 21
Gregory Pakosz Avatar answered Oct 31 '22 20:10

Gregory Pakosz


There's a new method that was introduced to NSCalendar with iOS 8 that makes this much easier.

- (NSComparisonResult)compareDate:(NSDate *)date1 toDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit NS_AVAILABLE(10_9, 8_0);

You set the granularity to the unit(s) that matter. This disregards all other units and limits comparison to the ones selected.

like image 41
static0886 Avatar answered Oct 31 '22 20:10

static0886