두 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.

11

1
@JoshCaswell 실제 복제 본인 경우 병합하지 않겠습니까? 당신은 전에 그것을 한 ...
Dan Rosenstark

1
다이아몬드 중재자 만 병합을 수행 할 수 있습니다 (@Yar).
jscs

답변:


658

두 날짜를 가정 해 봅시다.

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 : before를 사용한다고 생각하지 못했습니다.
SomaMan

11
나는 NSOrderedAscending <0 및 NSOrderedDescending> 0이라는 사실에 의존하고 싶습니다. 비교를 더 쉽게 읽을 수 있습니다. 지적했다. ;-)
jpap 10

글쎄-비교 방법은 일대일 오류만큼 오류가 발생하기 쉽습니다. 따라서 (NSDate *) laterDate : (NSDate *) anotherDate를 사용해야합니다. 예상 결과를 비교하면 끝입니다! "Waaait 내림차순 / 오름차순?!"
masi

@jpap 저도 엉망이되었습니다. Apple은 결과를 date1 -> date2오름차순 / 내림차순으로 생각하기를 원합니다 (따라서 date1은 각각 나중에 또는 더 빠름).
Ja͢ck

@ Jack은 요소를 순서대로 정렬하기 위해 알고리즘을 정렬하기 위해 마법의 숫자 (-1,0,1)가없는보다 추상적 인 방법입니다. 더 읽기 쉬운 이름으로 상수를 직접 재정의 할 수도 있습니다. 내 대답은 일을하고 있지만 읽을 수있는 코드의 수상자는 아닙니다. 아래로 스크롤하면 다른 좋은 것들이 있습니다.
닉 위버

50

파티에 늦었지만 NSDate 객체를 비교하는 또 다른 쉬운 방법은 객체를 '>' '<' '=='등을 쉽게 사용할 수 있도록 기본 유형으로 변환하는 것입니다.

예.

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

timeIntervalSinceReferenceDate참조 날짜 이후 날짜를 초로 변환합니다 (2001 년 1 월 1 일 GMT). 으로 timeIntervalSinceReferenceDate돌아갑니다 (더블 타입 정의 임) NSTimeInterval, 우리는 원시 비교기를 사용할 수 있습니다.


4
(NSComparisonResult)compare:(NSDate *)이 간단한 조작에 대해 약간 더 직관적 이지만 여전히 장황하다. (평소대로)
Pierre de LESPINAY

1
또한 할 수[dateA timeIntervalSinceDate:dateB] > 0
스콧 피스터에게

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

@JohnVanDijk 확장 프로그램 안에 넣을 수 없습니다. 확장명과 같은 파일에 넣었지만{ ... }
Andrew

13

NSDate 비교 기능이 있습니다.

compare:NSComparisonResult수신자의 시간 순서와 지정된 다른 날짜를 나타내는 값을 리턴합니다 .

(NSComparisonResult)compare:(NSDate *)anotherDate

매개 변수 : anotherDate 수신자를 비교할 날짜입니다. 이 값은 0이 아니어야합니다. 값이 nil이면 동작이 정의되지 않으며 이후 버전의 Mac OS X에서 변경 될 수 있습니다.

반환 값 :

  • 수신자와 anotherDate가 정확히 동일한 경우 NSOrderedSame
  • 수신자가 다른 날짜보다 늦은 시간이면 NSOrderedDescending
  • 수신자가 anotherDate보다 시간이 빠르면 NSOrderedAscending.

@ 아이린은 시간 구성 요소 만 다른 두 NSDate 객체를 비교하는 방법이 있습니까? 어떤 이유로 위의 방법이 작동하지 않습니다.
당신의

12

NSDate compare :, laterDate :, earlyDate : 또는 isEqualToDate : 메소드를 사용하려고합니다. 이 상황에서 <및> 연산자를 사용하면 날짜가 아닌 포인터를 비교합니다.


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

이것은 수신자의 이전과 anotherDate를 리턴합니다. 둘 다 동일하면 수신자가 리턴됩니다.


1
NSDates의 백업 개체는 컴파일 된 코드의 64 비트 버전에서 최적화되어 같은 시간을 나타내는 날짜가 같은 주소를 가지게됩니다. 따라서 cDate = [aDate earlierDate:bDate]그렇다면 cDate == aDate그리고 cDate == bDate둘 다 사실 일 수 있습니다. iOS 8에서 일부 날짜 작업을하는 것을 발견했습니다.
Ben Flynn

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


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;}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.