Cocoa -Touch: How do I see if two NSDates are on the same day?

I need to know if there are two instances of NSDate from the same day.

Is there an easier / better way to do this than get NSDateComponents and compare day / month / year?

+66
ios objective-c cocoa-touch macos
Oct 13 '09 at 16:59
source share
12 answers

NSDateComponents sounds like the best choice for me. Another tactic to try is accessing CFDate for free, then using CFDateGetAbsoluteTime and doing a subtraction to get the time span between the two dates. However, you will need to do additional math to find out if the time difference has dates on the same day.

+7
Oct 13 '09 at 17:04
source share

If you target iOS 8 (and OS X 10.9) or later , then Joe Response is the best solution using the new method in NSCalendar for this purpose only:

-[NSCalendar isDate:inSameDayAsDate:] 

For iOS 7 or earlier : NSDateComponents is my preference. How about something like this:

 - (BOOL)isSameDayWithDate1:(NSDate*)date1 date2:(NSDate*)date2 { NSCalendar* calendar = [NSCalendar currentCalendar]; unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit; NSDateComponents* comp1 = [calendar components:unitFlags fromDate:date1]; NSDateComponents* comp2 = [calendar components:unitFlags fromDate:date2]; return [comp1 day] == [comp2 day] && [comp1 month] == [comp2 month] && [comp1 year] == [comp2 year]; } 
+153
Oct 14 '09 at 1:51
source share

If you are running iOS 8, you can use -isDate:inSameDayAsDate:

From NSCalendar.h :

 /* This API compares the Days of the given dates, reporting them equal if they are in the same Day. */ - (BOOL)isDate:(NSDate *)date1 inSameDayAsDate:(NSDate *)date2 NS_AVAILABLE(10_9, 8_0); 

Please note that for some reason this did not make it into the official documentation on the Apple developer site. But this is definitely part of the public API.

+52
Jan 31 '15 at 2:40
source share

(Note: look at Joe's answer on a good way to do it on iOS 8+)

I just use the date format:

 NSDateFormatter *dateComparisonFormatter = [[[NSDateFormatter alloc] init] autorelease]; [dateComparisonFormatter setDateFormat:@"yyyy-MM-dd"]; if( [[dateComparisonFormatter stringFromDate:firstDate] isEqualToString:[dateComparisonFormatter stringFromDate:secondDate]] ) { … } 

NTN.

+24
Oct 13 '09 at 17:27
source share

In Swift:

 NSCalendar.currentCalendar().isDate(yourDate, equalToDate: yourOtherDate, toUnitGranularity: .Day) 

It will return true if they are on the same day.

+13
Jan 27 '16 at 20:27
source share

I like the progrmr solution, but I would go even further and create an NSDate category that provides this method. This will make your code a little more readable, and you will not need to copy and paste this method into each new class that it may need, just import the header file.

NSDate + SameDay.h

 @interface NSDate (SameDay) - (BOOL)isSameDayAsDate:(NSDate*)otherDate; @end 

NSDate + SameDay.m

 #import "NSDate+SameDay.h" @implementation NSDate (SameDay) - (BOOL)isSameDayAsDate:(NSDate*)otherDate { // From progrmr answer... NSCalendar* calendar = [NSCalendar currentCalendar]; unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit; NSDateComponents* comp1 = [calendar components:unitFlags fromDate:self]; NSDateComponents* comp2 = [calendar components:unitFlags fromDate:otherDate]; return [comp1 day] == [comp2 day] && [comp1 month] == [comp2 month] && [comp1 year] == [comp2 year]; } @end 



Then, after importing NSDate+SameDay.h into your class, you can use it like this:

 if ([myFirstDate isSameDayAsDate:mySecondDate]) { // The two dates are on the same day... } 
+11
Feb 05 '14 at 20:22
source share

I use NSDateComponents to highlight the time aspect and then compare. Something like:

 if ([[self beginningOfDay:date1] isEqualToDate:[self beginningOfDay:date2]]) { ... } - (NSDate *)beginningOfDay:(NSDate *)date { NSCalendar *calendar = [NSCalendar currentCalendar]; unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit; NSDateComponents *comp = [calendar components:unitFlags fromDate:date]; return [calendar dateFromComponents:comp]; } 
+5
Oct 13 '09 at 21:30
source share
 NSCalendar.currentCalendar().isDateInToday(yourNSDate) 

Available on iOS 8.0 and later and OS X version 10.9 and later.

+4
Jun 19 '16 at 3:20
source share

Is there an easier / better way to do this than get NSDateComponents and compare day / month / year?

Yes there is an easier way

-[NSCalendar rangeForUnit:startDate:interval:forDate:] These methods make it easy to set the date at the beginning of the unit (day, hour, month, year, ...) and get the length (interval) of this device.

As a category, it can be used as

 @interface NSDate (Comparison) -(BOOL) isSameDay:(NSDate *)rhs; @end @implementation NSDate (Comparison) -(BOOL)isSameDay:(NSDate *)rhs { NSDate *lhs = self; NSDate *lhsStart; NSDate *rhsStart; NSCalendar *cal = [NSCalendar currentCalendar]; [cal rangeOfUnit:NSCalendarUnitDay startDate:&lhsStart interval:NULL forDate:lhs]; [cal rangeOfUnit:NSCalendarUnitDay startDate:&rhsStart interval:NULL forDate:rhs]; return [lhsStart compare:rhsStart] == NSOrderedSame; } @end 

This category should work for all versions of iOS and Mac OS X 10.5 +.

for iOS 8+ and Mac OS X 10.9+ you can use NSCalendars

 - (BOOL)isDate:(NSDate *)date1 equalToDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit; 
+1
Mar 08 '15 at 0:02
source share

in Swift 3.0, iOS8 +

 if NSCalendar.current.isDate(Date(), equalTo: date, toGranularity: .day) { } 

or

 if NSCalendar.current.isDateInToday(date) { } 
+1
Mar 17 '17 at 20:05
source share

I create my own utility classes.

ZYUtility.h

 @interface ZYUtility : NSObject + (NSDate *)yesterday; + (NSDate *)tomorrow; + (NSDate *)endOfDay:(NSDate *)date; + (NSDate *)beginningOfDay:(NSDate *)date; @end 

ZYUtility.m

 + (NSDate *)yesterday; { NSCalendar *calendar = [NSCalendar currentCalendar]; NSDateComponents *componets = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:[NSDate date]]; componets.day -= 1; componets.hour = 24; componets.minute = 0; componets.second = 0; return [calendar dateFromComponents:componets]; } + (NSDate *)tomorrow; { NSCalendar *calendar = [NSCalendar currentCalendar]; NSDateComponents *componets = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:[NSDate date]]; componets.day += 1; componets.hour = 0; componets.minute = 0; componets.second = 0; return [calendar dateFromComponents:componets]; } + (NSDate *)beginningOfDay:(NSDate *)date { NSCalendar *calendar = [NSCalendar currentCalendar]; unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit; NSDateComponents *comp = [calendar components:unitFlags fromDate:date]; return [calendar dateFromComponents:comp]; } + (NSDate *)endOfDay:(NSDate *)date { NSCalendar *calendar = [NSCalendar currentCalendar]; NSDateComponents *components = [NSDateComponents new]; components.day = 1; NSDate *theDate = [calendar dateByAddingComponents:components toDate:[ZYUtility beginningOfDay:date] options:0]; theDate = [theDate dateByAddingTimeInterval:-1]; return theDate; } 
-one
May 17 '14 at 3:05
source share

The following will check if two dates on the same day correspond to a given era (which is sufficient in many cases):

 - (BOOL)isDate:(NSDate *)date1 sameDayAsDate:(NSDate *)date2 { NSCalendar *calendar = [NSCalendar currentCalendar]; int diff = [calendar ordinalityOfUnit:NSDayCalendarUnit inUnit:NSEraCalendarUnit forDate:date1] - [calendar ordinalityOfUnit:NSDayCalendarUnit inUnit:NSEraCalendarUnit forDate:date2]; return 0 == diff; } 
-one
Aug 21 '14 at 23:03
source share



All Articles