How to compare two NSDates: Which is more recent?
I am trying to achieve a dropBox sync and need to compare the dates of two files. One is on my dropBox account and one is on my iPhone.
I came up with the following, but I get unexpected results. I guess I'm doing something fundamentally wrong when comparing the two dates. I simply used the > < operators, but I guess this is no good as I am comparing two NSDate strings. Here we go:
NSLog(@"dB...lastModified: %@", dbObject.lastModifiedDate);
NSLog(@"iP...lastModified: %@", [self getDateOfLocalFile:@"NoteBo开发者_运维百科ok.txt"]);
if ([dbObject lastModifiedDate] < [self getDateOfLocalFile:@"NoteBook.txt"]) {
NSLog(@"...db is more up-to-date. Download in progress...");
[self DBdownload:@"NoteBook.txt"];
NSLog(@"Download complete.");
} else {
NSLog(@"...iP is more up-to-date. Upload in progress...");
[self DBupload:@"NoteBook.txt"];
NSLog(@"Upload complete.");
}
This gave me the following (random & wrong) output:
2011-05-11 14:20:54.413 NotePage[6918:207] dB...lastModified: 2011-05-11 13:18:25 +0000
2011-05-11 14:20:54.414 NotePage[6918:207] iP...lastModified: 2011-05-11 13:20:48 +0000
2011-05-11 14:20:54.415 NotePage[6918:207] ...db is more up-to-date.
or this one which happens to be correct:
2011-05-11 14:20:25.097 NotePage[6903:207] dB...lastModified: 2011-05-11 13:18:25 +0000
2011-05-11 14:20:25.098 NotePage[6903:207] iP...lastModified: 2011-05-11 13:19:45 +0000
2011-05-11 14:20:25.099 NotePage[6903:207] ...iP is more up-to-date.
Let's assume two dates:
NSDate *date1;
NSDate *date2;
Then the following comparison will tell which is earlier/later/same:
if ([date1 compare:date2] == NSOrderedDescending) {
NSLog(@"date1 is later than date2");
} else if ([date1 compare:date2] == NSOrderedAscending) {
NSLog(@"date1 is earlier than date2");
} else {
NSLog(@"dates are the same");
}
Please refer to the NSDate class documentation for more details.
Late to the party, but another easy way of comparing NSDate objects is to convert them into primitive types which allows for easy use of '>' '<' '==' etc
eg.
if ([dateA timeIntervalSinceReferenceDate] > [dateB timeIntervalSinceReferenceDate]) {
//do stuff
}
timeIntervalSinceReferenceDate
converts the date into seconds since the reference date (1 January 2001, GMT). As timeIntervalSinceReferenceDate
returns a NSTimeInterval (which is a double typedef), we can use primitive comparators.
In Swift, you can overload existing operators:
func > (lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.timeIntervalSinceReferenceDate > rhs.timeIntervalSinceReferenceDate
}
func < (lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.timeIntervalSinceReferenceDate < rhs.timeIntervalSinceReferenceDate
}
Then, you can compare NSDates directly with <
, >
, and ==
(already supported).
NSDate
has a compare function.
compare:
Returns an NSComparisonResult
value that indicates the temporal ordering of the receiver and another given date.
(NSComparisonResult)compare:(NSDate *)anotherDate
Parameters: anotherDate
The date with which to compare the receiver.
This value must not be nil. If the value is nil, the behavior is undefined and may change in future versions of Mac OS X.
Return Value:
- If the receiver and anotherDate are exactly equal to each other,
NSOrderedSame
- If the receiver is later in time than anotherDate,
NSOrderedDescending
- If the receiver is earlier in time than anotherDate,
NSOrderedAscending
.
You want to use the NSDate compare:, laterDate:, earlierDate:, or isEqualToDate: methods. Using the < and > operators in this situation is comparing the pointers, not the dates
- (NSDate *)earlierDate:(NSDate *)anotherDate
This returns the earlier of the receiver and anotherDate. If both are same, the receiver is returned.
Some date utilities, including comparisons IN ENGLISH, which is nice:
#import <Foundation/Foundation.h>
@interface NSDate (Util)
-(BOOL) isLaterThanOrEqualTo:(NSDate*)date;
-(BOOL) isEarlierThanOrEqualTo:(NSDate*)date;
-(BOOL) isLaterThan:(NSDate*)date;
-(BOOL) isEarlierThan:(NSDate*)date;
- (NSDate*) dateByAddingDays:(int)days;
@end
The implementation:
#import "NSDate+Util.h"
@implementation NSDate (Util)
-(BOOL) isLaterThanOrEqualTo:(NSDate*)date {
return !([self compare:date] == NSOrderedAscending);
}
-(BOOL) isEarlierThanOrEqualTo:(NSDate*)date {
return !([self compare:date] == NSOrderedDescending);
}
-(BOOL) isLaterThan:(NSDate*)date {
return ([self compare:date] == NSOrderedDescending);
}
-(BOOL) isEarlierThan:(NSDate*)date {
return ([self compare:date] == NSOrderedAscending);
}
- (NSDate *) dateByAddingDays:(int)days {
NSDate *retVal;
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:days];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
retVal = [gregorian dateByAddingComponents:components toDate:self options:0];
return retVal;
}
@end
You should use :
- (NSComparisonResult)compare:(NSDate *)anotherDate
to compare dates. There is no operator overloading in objective C.
Why don't you guys use these NSDate
compare methods:
- (NSDate *)earlierDate:(NSDate *)anotherDate;
- (NSDate *)laterDate:(NSDate *)anotherDate;
I have encounter almost same situation, but in my case I'm checking if number of days difference
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *compDate = [cal components:NSDayCalendarUnit fromDate:fDate toDate:tDate options:0];
int numbersOfDaysDiff = [compDate day]+1; // do what ever comparison logic with this int.
Useful when you need to compare NSDate in Days/Month/Year unit
You can compare two date by this method also
switch ([currenttimestr compare:endtimestr])
{
case NSOrderedAscending:
// dateOne is earlier in time than dateTwo
break;
case NSOrderedSame:
// The dates are the same
break;
case NSOrderedDescending:
// dateOne is later in time than dateTwo
break;
}
Use this simple function for date comparison
-(BOOL)dateComparision:(NSDate*)date1 andDate2:(NSDate*)date2{
BOOL isTokonValid;
if ([date1 compare:date2] == NSOrderedDescending) {
NSLog(@"date1 is later than date2");
isTokonValid = YES;
} else if ([date1 compare:date2] == NSOrderedAscending) {
NSLog(@"date1 is earlier than date2");
isTokonValid = NO;
} else {
isTokonValid = NO;
NSLog(@"dates are the same");
}
return isTokonValid;}
I have tried it hope it works for you
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
int unitFlags =NSDayCalendarUnit;
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
NSDate *myDate; //= [[NSDate alloc] init];
[dateFormatter setDateFormat:@"dd-MM-yyyy"];
myDate = [dateFormatter dateFromString:self.strPrevioisDate];
NSDateComponents *comps = [gregorian components:unitFlags fromDate:myDate toDate:[NSDate date] options:0];
NSInteger day=[comps day];
精彩评论