如何比较两个NSDate:哪个是最新的?


244

我正在尝试实现dropBox同步,并且需要比较两个文件的日期。一个在我的dropBox帐户上,另一个在我的iPhone上。

我提出了以下建议,但是得到了意想不到的结果。我猜比较两个日期时我做的是根本错误的事情。我只是使用了> <运算符,但是我猜这不好,因为我正在比较两个NSDate字符串。开始了:

NSLog(@"dB...lastModified: %@", dbObject.lastModifiedDate); 
NSLog(@"iP...lastModified: %@", [self getDateOfLocalFile:@"NoteBook.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.");
}

这给了我以下(随机和错误)输出:

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.

或这恰好是正确的:

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.


1
@JoshCaswell如果它是真实副本,为什么不合并它们?您之前做过……
Dan Rosenstark 2014年

1
只有钻石版主可以执行@Yar合并。
jscs 2014年

Answers:


657

让我们假设两个日期:

NSDate *date1;
NSDate *date2;

然后,下面的比较将说明哪个是较早/较晚/相同:

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");
}

请参阅NSDate类文档以获取更多详细信息。


可爱!与[date1 earlyDate:date2]等混为一谈...谢谢-由于某些原因,我从没想过使用compare:。
SomaMan '04 -4-20

11
我喜欢依靠NSOrderedAscending <0和NSOrderedDescending> 0的事实。这使得比较易于阅读:[date1 compare:date2] <0 / * date1 <date2 * /并避免了(容易犯的)@albertamg错误指出。;-)
jpap 2013年

好吧-比较方法与一次性错误一样容易出错。因此,您应该使用(NSDate *)laterDate:(NSDate *)anotherDate,这将返回两者的较晚日期。因此,您只需比较您的预期结果就可以了!不要摆弄“ Waaait下降/上升吗?!”
2014年

@jpap也把我弄乱了;似乎Apple希望您将结果视为date1 -> date2升序/降序(因此date1分别晚于或早于)。
2014年

@Jack是一种没有魔术数字(-1,0,1)的更抽象的方法,用于对算法进行排序以将元素排序。您也可以使用更具可读性的名称自己重新定义这些常量。我的回答是完成工作,但不是可读代码的获奖者。向下滚动,还有其他好的。
尼克·韦弗

50

晚了,但是比较NSDate对象的另一种简便方法是将它们转换为原始类型,从而可以轻松使用'>''<''=='等

例如。

if ([dateA timeIntervalSinceReferenceDate] > [dateB timeIntervalSinceReferenceDate]) {
    //do stuff
}

timeIntervalSinceReferenceDate将日期转换为自参考日期(格林尼治标准时间2001年1月1日)以来的秒数。当timeIntervalSinceReferenceDate返回NSTimeInterval(它是一个double typedef)时,我们可以使用原始比较器。


4
(NSComparisonResult)compare:(NSDate *)这个简单的操作比它稍微直观一些,但仍然很冗长...(与往常一样)
Pierre de LESPINAY 2014年

1
也可以做[dateA timeIntervalSinceDate:dateB] > 0
Scott Fister 18'Aug

14

在Swift中,您可以重载现有的运算符:

func > (lhs: NSDate, rhs: NSDate) -> Bool {
    return lhs.timeIntervalSinceReferenceDate > rhs.timeIntervalSinceReferenceDate
}

func < (lhs: NSDate, rhs: NSDate) -> Bool {
    return lhs.timeIntervalSinceReferenceDate < rhs.timeIntervalSinceReferenceDate
}

然后,你可以直接比较NSDates <>==(已经支持)。


如果我尝试对此进行扩展,会得到“仅在全局范围内允许操作员”的建议吗?
JohnVanDijk,2015年

@JohnVanDijk您不能将其放在扩展中。我将其与扩展名放在相同的文件中,但在{ ... }
Andrew

13

NSDate 具有比较功能。

compare:返回一个NSComparisonResult值,该值指示接收者的时间顺序和另一个给定的日期。

(NSComparisonResult)compare:(NSDate *)anotherDate

参数anotherDate 与接收者进行比较的日期。该值不能为nil。如果值为nil,则行为是不确定的,并且在Mac OS X的将来版本中可能会更改。

返回值:

  • 如果接收者和另一个日期彼此完全相同, NSOrderedSame
  • 如果接收方的时间晚于另一个日期, NSOrderedDescending
  • 如果接收器的时间早于anotherDate,则NSOrderedAscending

@Irene是否可以比较两个NSDate对象,其中仅时间分量不同?由于某种原因,上述方法不起作用。
2012年

12

您要使用NSDate compare :、 LaterDate :、 earlyDate:或isEqualToDate:方法。在这种情况下,使用<和>运算符是比较指针,而不是日期


11
- (NSDate *)earlierDate:(NSDate *)anotherDate

这将返回接收者中的较早者和另一个日期。如果两者相同,则返回接收者。


1
请注意,可以在已编译代码的64位版本上优化NSDates的后备对象,以使表示相同时间的日期具有相同的地址。因此,如果cDate = [aDate earlierDate:bDate]cDate == aDatecDate == bDate既可以是真实的。发现这个做iOS上的8某个日期的工作
本·弗林

1
相反,在32位平台上,如果日期不同,则-earlierDate:(和-laterDate:)既不返回接收方也不返回参数。
Ben Lings

7

一些日期实用程序,包括英语比较,这很不错:

#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

实现:

#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

1
或者只是使用:github.com/erica/NSDate-Extensions
Dan Rosenstark 2014年


6

您应该使用:

- (NSComparisonResult)compare:(NSDate *)anotherDate

比较日期。目标C中没有运算符重载。


6

你们为什么不使用这些NSDate比较方法:

- (NSDate *)earlierDate:(NSDate *)anotherDate;
- (NSDate *)laterDate:(NSDate *)anotherDate;

4

我遇到了几乎相同的情况,但我要检查的是天数是否有差异

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.

当您需要以天/月/年为单位比较NSDate时很有用


NSDayCalendarUnit已弃用,因此请改用NSCalendarUnitDay
Mazen Kasser

2

您也可以通过这种方法比较两个日期

        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;

        }

0

我已经尝试过了,希望对你有用

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];

0

使用此简单功能进行日期比较

-(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;}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.