İki NSDate nasıl karşılaştırılır: Hangisi daha yeni?


244

Bir dropBox senkronizasyonu elde etmeye çalışıyorum ve iki dosyanın tarihlerini karşılaştırmanız gerekiyor. Bir tanesi dropBox hesabımda, diğeri iPhone'umda.

Aşağıdakileri buldum, ama beklenmedik sonuçlar elde ediyorum. Sanırım iki tarihi karşılaştırırken temelde yanlış bir şey yapıyorum. Ben sadece> <operatörlerini kullandım, ama sanırım iki NSDate dizesini karşılaştırdığımda bu iyi değil. İşte başlıyoruz:

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

Bu bana aşağıdaki (rastgele ve yanlış) çıktı verdi:

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.

veya doğru olan şu:

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
jscs

1
@JoshCaswell gerçek bir kopya ise, neden onları birleştirmiyorsunuz? Daha önce yaptın ...
Dan Rosenstark

1
Sadece elmas moderatörleri birleştirme yapabilir, @Yar.
jscs

Yanıtlar:


658

İki tarih kabul edelim:

NSDate *date1;
NSDate *date2;

Sonra aşağıdaki karşılaştırma hangisinin daha önce / daha sonra / aynı olduğunu söyleyecektir:

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

Daha fazla bilgi için lütfen NSDate sınıfı belgelerine bakın.


Güzel! [Date1 earlyDate: date2] vb.
SomaMan

11
NSOrderedAscending <0 ve NSOrderedDescending> 0 olduğuna güvenmeyi seviyorum. Bu karşılaştırmayı okumayı kolaylaştırır: [tarih1 karşılaştır: tarih2] <0 / * tarih1 <tarih2 * / ve (yapmak kolay) hata @albertamg dikkat çekti. ;-)
jpap

Peki - karşılaştırma yöntemi hata hatalar kadar hataya açıktır. Bu nedenle, (NSDate *) laterDate: (NSDate *), her ikisinin de sonraki tarihini döndürecek bir anotherDate kullanmalısınız. böylece sadece beklenen sonucu karşılaştırırsınız ve işiniz biter! "Waaait azalan / artan?!"
masi

@jpap Bu da beni mahvetti; Apple sonucu sizden date1 -> date2artan / azalan gibi düşünmenizi istiyor (ve bu nedenle tarih1 sırasıyla veya daha erken).
Ja͢ck

@Jack, öğeleri sıralamak için algoritmaları sıralamak için sihirli numaralar (-1,0,1) olmadan daha soyut bir yol. Ayrıca bu sabitleri daha okunabilir bir adla yeniden tanımlayabilirsiniz. Cevabım işi yapmak ama okunabilir kodun ödüllü değil. Aşağı kaydırın, başka iyi olanlar da var.
Nick Weaver

50

Partiye geç, ancak NSDate nesnelerini karşılaştırmanın bir başka kolay yolu, onları '>' '<' '==' vb. Kolay kullanımına izin veren ilkel türlere dönüştürmektir.

Örneğin.

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

timeIntervalSinceReferenceDatetarihi referans tarihinden sonraki saniyeye dönüştürür (1 Ocak 2001, GMT). timeIntervalSinceReferenceDateBir NSTimeInterval döndürdüğü gibi (bu bir double typedef), ilkel karşılaştırıcılar kullanabiliriz.


4
(NSComparisonResult)compare:(NSDate *)Bu basit işlem için biraz daha sezgisel ama yine de oldukça ayrıntılı ... (her zamanki gibi)
Pierre de LESPINAY

1
da yapabilir[dateA timeIntervalSinceDate:dateB] > 0
Scott Fister

14

Swift'te mevcut operatörleri aşırı yükleyebilirsiniz:

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

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

Ardından, doğrudan NSDates karşılaştırabilirsiniz <, >ve ==(zaten desteklenir).


Bunun bir uzantısını yapmaya çalışırsam, "Operatörler yalnızca küresel kapsamda izin verilir", öneriler?
JohnVanDijk

@ JohnVanDijk bir uzantının içine koyamazsınız. Uzantıyla aynı dosyaya { ... }
Andrew

13

NSDate karşılaştırma işlevine sahiptir.

compare:NSComparisonResultAlıcının geçici sırasını ve verilen başka bir tarihi gösteren bir değer döndürür .

(NSComparisonResult)compare:(NSDate *)anotherDate

Parametreler : anotherDate Alıcının karşılaştırılacağı tarih. Bu değer sıfır olmamalıdır. Değer nil ise, davranış tanımsızdır ve Mac OS X'in gelecekteki sürümlerinde değişebilir.

Geri dönüş değeri:

  • Alıcı ve anotherDate tam olarak eşitse, NSOrderedSame
  • Alıcı, başka bir Tarihten daha sonraysa, NSOrderedDescending
  • Alıcı zaman içinde başka bir Tarihten daha erkense NSOrderedAscending,.

@Irene, yalnızca zaman bileşeninin farklı olduğu iki NSDate nesnesini karşılaştırmanın bir yolu var mı? Nedense yukarıdaki yöntem işe yaramıyor.
Faydalı

12

NSDate compar :, laterDate :, earlyDate :, veya isEqualToDate: yöntemlerini kullanmak istiyorsunuz. Bu durumda <ve> operatörlerini kullanmak tarihleri ​​değil işaretçileri karşılaştırır


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

Bu, alıcının erken saatini ve anotherDate değerini döndürür. Her ikisi de aynı ise, alıcı iade edilir.


1
NSDates'in yedekleme nesnesinin, derlenmiş kodunuzun 64 bit sürümlerinde aynı zamanı temsil eden tarihlerin aynı adrese sahip olacağı şekilde optimize edilebileceğini unutmayın. Böylece o cDate = [aDate earlierDate:bDate]zaman cDate == aDateve cDate == bDateher ikisi de doğru olabilir. Bunu iOS 8'de bir tarih çalışması yaptı.
Ben Flynn

1
Tersine, 32 bit platformlarda, tarihler aynı değilse, -earlierDate:(ve -laterDate:) ne alıcı ne de argüman döndüremez.
Ben Lings

7

İNGİLİZCE karşılaştırmaları da dahil olmak üzere bazı tarih yardımcı programları, güzel:

#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

Hayata geçirme:

#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
Ya da sadece şunu kullanın: github.com/erica/NSDate-Extensions
Dan Rosenstark


6

Kullanmalısın :

- (NSComparisonResult)compare:(NSDate *)anotherDate

tarihleri ​​karşılaştırmak. Hedef C'de operatör aşırı yüklenmesi yok.


6

Neden bu NSDatekarşılaştırma yöntemlerini kullanmıyorsunuz :

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

4

Neredeyse aynı durumla karşılaşıyorum, ancak benim durumumda gün sayısı farkının olup olmadığını kontrol ediyorum

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.

Gün / Ay / Yıl biriminde NSDate'i karşılaştırmanız gerektiğinde kullanışlıdır


NSDayCalendarUnit kullanımdan kaldırıldı, bu nedenle NSCalendarUnitDay kullanın
Mazen Kasser

2

Bu yöntemle iki tarihi de karşılaştırabilirsiniz

        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

Bunu denedim, umarım senin için çalışır

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

Tarih karşılaştırması için bu basit işlevi kullanın

-(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;}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.