Was ist der effizienteste / empfohlene Weg, um zwei NSDates zu vergleichen? Ich möchte in der Lage sein zu sehen, ob beide Daten unabhängig von der Uhrzeit am selben Tag liegen, und habe begonnen, Code zu schreiben, der die timeIntervalSinceDate: -Methode innerhalb der NSDate-Klasse verwendet und die Ganzzahl dieses Werts geteilt durch die Anzahl der Sekunden erhält in einem Tag. Das scheint langwierig und ich habe das Gefühl, dass mir etwas Offensichtliches fehlt.
Der Code, den ich zu beheben versuche, lautet:
if (!([key compare:todaysDate] == NSOrderedDescending))
{
todaysDateSection = [eventSectionsArray count] - 1;
}
Dabei sind key und todaysDate NSDate-Objekte und todaysDate wird erstellt mit:
NSDate *todaysDate = [[NSDate alloc] init];
Grüße
Dave
iphone
objective-c
nsdate
Zauberkugel Dave
quelle
quelle
Antworten:
Sie stellen die Uhrzeit im Datum auf 00:00:00 ein, bevor Sie den Vergleich durchführen:
unsigned int flags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay; NSCalendar* calendar = [NSCalendar currentCalendar]; NSDateComponents* components = [calendar components:flags fromDate:date]; NSDate* dateOnly = [calendar dateFromComponents:components]; // ... necessary cleanup
Dann können Sie die Datumswerte vergleichen. Siehe die Übersicht in der Referenzdokumentation .
quelle
Ich bin überrascht, dass keine anderen Antworten diese Option haben, um das "Beginn des Tages" -Datum für die Objekte zu erhalten:
[[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date1 interval:NULL forDate:date1]; [[NSCalendar currentCalendar] rangeOfUnit:NSCalendarUnitDay startDate:&date2 interval:NULL forDate:date2];
Welche setzt
date1
unddate2
an den Anfang ihrer jeweiligen Tage. Wenn sie gleich sind, sind sie am selben Tag.Oder diese Option:
NSUInteger day1 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit inUnit: forDate:date1]; NSUInteger day2 = [[NSCalendar currentCalendar] ordinalityOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitEra forDate:date2];
Welche setzt
day1
undday2
auf etwas willkürliche Werte, die verglichen werden können. Wenn sie gleich sind, sind sie am selben Tag.quelle
NSDayCalendarUnit
wurde veraltet und wird ersetzt durchNSCalendarUnitDay
Es gibt eine neue Methode, die mit iOS 8 in NSCalendar eingeführt wurde und dies erheblich vereinfacht.
- (NSComparisonResult)compareDate:(NSDate *)date1 toDate:(NSDate *)date2 toUnitGranularity:(NSCalendarUnit)unit NS_AVAILABLE(10_9, 8_0);
Sie legen die Granularität auf die Einheit (en) fest, die wichtig sind. Dies ignoriert alle anderen Einheiten und schränkt den Vergleich mit den ausgewählten ein.
quelle
compareDate:toDate:toUnitGranularity:
unter iOS> = 8 aufgelistet habe . Sobald Sie die Unterstützung für Betriebssystemversionen <8 einstellen, können Sie die Implementierung auf den Aufruf von reduzierencompareDate:toDate:toUnitGranularity:
.differenceBetweenDate:andDate:usingUnit:
natürlich, negative, null oder positive ganzzahlige Werte zurückzugeben, die den Betrag der Differenz zwischen den Daten in der angeforderten Uint angeben.Für iOS8 und höher ist die Überprüfung, ob zwei Daten am selben Tag auftreten, so einfach wie:
[[NSCalendar currentCalendar] isDate:date1 inSameDayAsDate:date2]
Siehe Dokumentation
quelle
Dies ist eine Abkürzung aller Antworten:
NSInteger interval = [[[NSCalendar currentCalendar] components: NSDayCalendarUnit fromDate: date1 toDate: date2 options: 0] day]; if(interval<0){ //date1<date2 }else if (interval>0){ //date2<date1 }else{ //date1=date2 }
quelle
Ich habe den Duncan C-Ansatz verwendet und einige Fehler behoben, die er gemacht hat
-(NSInteger) daysBetweenDate:(NSDate *)firstDate andDate:(NSDate *)secondDate { NSCalendar *currentCalendar = [NSCalendar currentCalendar]; NSDateComponents *components = [currentCalendar components: NSDayCalendarUnit fromDate: firstDate toDate: secondDate options: 0]; NSInteger days = [components day]; return days; }
quelle
Ich benutze diese kleine util-Methode:
-(NSDate*)normalizedDateWithDate:(NSDate*)date { NSDateComponents* components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate: date]; return [calendar_ dateFromComponents:components]; // NB calendar_ must be initialized }
(Sie benötigen offensichtlich einen Ivar
calendar_
mit einemNSCalendar
.)Auf diese Weise können Sie leicht überprüfen, ob ein Datum heute so ist:
[[self normalizeDate:aDate] isEqualToDate:[self normalizeDate:[NSDate date]]];
(
[NSDate date]
Gibt das aktuelle Datum und die aktuelle Uhrzeit zurück.)Dies ist natürlich sehr ähnlich zu dem, was Gregory vorschlägt. Der Nachteil dieses Ansatzes besteht darin, dass er dazu neigt, viele temporäre
NSDate
Objekte zu erstellen . Wenn Sie viele Daten verarbeiten möchten, würde ich empfehlen, eine andere Methode zu verwenden, z. B. die Komponenten direkt zu vergleichen oderNSDateComponents
stattdessen mit Objekten zu arbeitenNSDates
.quelle
Die Antwort ist einfacher als jeder denkt. NSCalendar hat eine Methode
Mit dieser Methode können Sie die Differenz zwischen zwei Daten mit den gewünschten Einheiten berechnen.
Schreiben Sie also eine Methode wie diese:
-(NSInteger) daysBetweenDate: (NSDate *firstDate) andDate: (NSDate *secondDate) { NSCalendar *currentCalendar = [NSCalendar currentCalendar]; NSDateComponents components* = [currentCalendar components: NSDayCalendarUnit fromDate: firstDate toDate: secondDate options: 0]; NSInteger days = [components days]; return days; }
Wenn die obige Methode Null zurückgibt, befinden sich die beiden Daten am selben Tag.
quelle
Ab iOS 8.0 können Sie Folgendes verwenden:
NSCalendar *calendar = [NSCalendar currentCalendar]; NSComparisonResult dateComparison = [calendar compareDate:[NSDate date] toDate:otherNSDate toUnitGranularity:NSCalendarUnitDay];
Wenn das Ergebnis zB NSOrderedDescending ist, liegt otherDate in Tagen vor [NSDate date].
Ich sehe diese Methode nicht in der NSCalendar-Dokumentation, aber in den API-Unterschieden zwischen iOS 7.1 und iOS 8.0
quelle
Mit Swift 3 können Sie je nach Bedarf eines der beiden folgenden Muster auswählen, um Ihr Problem zu lösen.
# 1. Mit
compare(_:to:toGranularity:)
MethodeCalendar
hat eine Methode namenscompare(_:to:toGranularity:)
.compare(_:to:toGranularity:)
hat die folgende Erklärung:Der folgende Spielplatzcode zeigt, wie heiß es ist, ihn zu verwenden:
import Foundation let calendar = Calendar.current let date1 = Date() // "Mar 31, 2017, 2:01 PM" let date2 = calendar.date(byAdding: .day, value: -1, to: date1)! // "Mar 30, 2017, 2:01 PM" let date3 = calendar.date(byAdding: .hour, value: 1, to: date1)! // "Mar 31, 2017, 3:01 PM" /* Compare date1 and date2 */ do { let comparisonResult = calendar.compare(date1, to: date2, toGranularity: .day) switch comparisonResult { case ComparisonResult.orderedSame: print("Same day") default: print("Not the same day") } // Prints: "Not the same day" } /* Compare date1 and date3 */ do { let comparisonResult = calendar.compare(date1, to: date3, toGranularity: .day) if case ComparisonResult.orderedSame = comparisonResult { print("Same day") } else { print("Not the same day") } // Prints: "Same day" }
# 2. Verwenden von
dateComponents(_:from:to:)
Calendar
hat eine Methode namensdateComponents(_:from:to:)
.dateComponents(_:from:to:)
hat die folgende Erklärung:Der folgende Spielplatzcode zeigt, wie heiß es ist, ihn zu verwenden:
import Foundation let calendar = Calendar.current let date1 = Date() // "Mar 31, 2017, 2:01 PM" let date2 = calendar.date(byAdding: .day, value: -1, to: date1)! // "Mar 30, 2017, 2:01 PM" let date3 = calendar.date(byAdding: .hour, value: 1, to: date1)! // "Mar 31, 2017, 3:01 PM" /* Compare date1 and date2 */ do { let dateComponents = calendar.dateComponents([.day], from: date1, to: date2) switch dateComponents.day { case let value? where value < 0: print("date2 is before date1") case let value? where value > 0: print("date2 is after date1") case let value? where value == 0: print("date2 equals date1") default: print("Could not compare dates") } // Prints: date2 is before date1 } /* Compare date1 and date3 */ do { let dateComponents = calendar.dateComponents([.day], from: date1, to: date3) switch dateComponents.day { case let value? where value < 0: print("date2 is before date1") case let value? where value > 0: print("date2 is after date1") case let value? where value == 0: print("date2 equals date1") default: print("Could not compare dates") } // Prints: date2 equals date1 }
quelle
Für Entwickler, die in Swift 3 codieren
if(NSCalendar.current.isDate(selectedDate, inSameDayAs: NSDate() as Date)){ // Do something }
quelle
int interval = (int)[firstTime timeIntervalSinceDate:secondTime]/(60*60*24); if (interval!=0){ //not the same day; }
quelle
Meine Lösung waren zwei Konvertierungen mit NSDateFormatter:
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init]; [dateFormat setDateFormat:@"yyyyMMdd"]; [dateFormat setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]]; NSDate *today = [NSDate dateWithTimeIntervalSinceNow:0]; NSString *todayString=[dateFormat stringFromDate:today]; NSDate *todayWithoutHour=[dateFormat dateFromString:todayString]; if ([today compare:exprDate] == NSOrderedDescending) { //do }
quelle
Die Dokumentation in Bezug auf NSDate zeigt an, dass die
compare:
undisEqual:
Methoden sowohl einen grundlegenden Vergleich durchführen und die Ergebnisse zu bestellen, wenn auch sie noch Faktor in der Zeit.Der wahrscheinlich einfachste Weg, die Aufgabe zu verwalten, besteht darin, eine neue
isToday
Methode zu erstellen, die Folgendes bewirkt:- (bool)isToday:(NSDate *)otherDate { currentTime = [however current time is retrieved]; // Pardon the bit of pseudo-code if (currentTime < [otherDate timeIntervalSinceNow]) { return YES; } else { return NO; } }
quelle
Dies ist eine besonders hässliche Katze für die Haut, aber hier ist eine andere Möglichkeit, dies zu tun. Ich sage nicht, dass es elegant ist, aber es ist wahrscheinlich so nah wie möglich an der Datums- / Zeitunterstützung in iOS.
bool isToday = [[NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle] isEqualToString:[NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterFullStyle timeStyle:NSDateFormatterNoStyle]];
quelle
NSUInteger unit = NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit; NSDateComponents *comp = [cal components:unit fromDate:nowDate toDate:setDate options:0]; NSString *dMonth; dMonth = [NSString stringWithFormat:@"%02ld",comp.month]; NSString *dDay; dDay = [NSString stringWithFormat:@"%02ld",comp.day + (comp.hour > 0 ? 1 : 0)];
Vergleichen Sie auch die Stunde, um den Unterschied von 1 Tag zu beheben
quelle