iphone - Cómo comparar dos NSDates: ¿Cuál es más reciente?
objective-c cocoa-touch (13)
¿Por qué no usan estos métodos de comparación de NSDate
?
- (NSDate *)earlierDate:(NSDate *)anotherDate;
- (NSDate *)laterDate:(NSDate *)anotherDate;
Estoy tratando de lograr una sincronización de DropBox y necesito comparar las fechas de dos archivos. Uno está en mi cuenta de DropBox y otro está en mi iPhone.
Se me ocurrió lo siguiente, pero obtengo resultados inesperados. Supongo que estoy haciendo algo fundamentalmente mal al comparar las dos fechas. Simplemente utilicé los operadores> <, pero supongo que esto no es bueno ya que estoy comparando dos cadenas NSDate. Aquí vamos:
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.");
}
Esto me dio la siguiente salida (aleatoria e incorrecta):
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.
o este que resulta ser correcto:
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.
Algunas utilidades de fecha, incluyendo comparaciones EN INGLÉS, lo cual es bueno:
#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
La implementación:
#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
Asumamos dos fechas:
NSDate *date1;
NSDate *date2;
Entonces la siguiente comparación dirá cuál es anterior / posterior / igual:
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");
}
Por favor, consulte la documentación de la clase NSDate para más detalles.
Deberías usar :
- (NSComparisonResult)compare:(NSDate *)anotherDate
para comparar fechas. No hay sobrecarga del operador en el objetivo C.
Desea utilizar los métodos NSDate compare :, laterDate :, earlyDate: o isEqualToDate:. Usar los operadores <y> en esta situación es comparar los punteros, no las fechas
En Swift, puede sobrecargar los operadores existentes:
func > (lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.timeIntervalSinceReferenceDate > rhs.timeIntervalSinceReferenceDate
}
func < (lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.timeIntervalSinceReferenceDate < rhs.timeIntervalSinceReferenceDate
}
Luego, puede comparar NSDates directamente con <
, >
y ==
(ya admitido).
Lo he intentado espero que te funcione.
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];
Tarde a la fiesta, pero otra manera fácil de comparar objetos de NSDate es convertirlos en tipos primitivos que permite el uso fácil de ''>'' ''<'' ''=='' etc.
p.ej.
if ([dateA timeIntervalSinceReferenceDate] > [dateB timeIntervalSinceReferenceDate]) {
//do stuff
}
timeIntervalSinceReferenceDate
convierte la fecha en segundos desde la fecha de referencia (1 de enero de 2001, GMT). Como timeIntervalSinceReferenceDate
devuelve un NSTimeInterval (que es un typedef doble), podemos usar comparadores primitivos.
Tengo casi la misma situación, pero en mi caso, estoy comprobando si la cantidad de días es diferente
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.
Útil cuando necesitas comparar NSDate en unidad de días / mes / año
Utilice esta función simple para la comparación de fechas
-(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;}
NSDate
tiene una función de comparación.
compare:
devuelve un valor NSComparisonResult
que indica el orden temporal del receptor y otra fecha dada.
(NSComparisonResult)compare:(NSDate *)anotherDate
Parámetros : anotherDate
La fecha con la que se compara el receptor. Este valor no debe ser nulo. Si el valor es nulo, el comportamiento no está definido y puede cambiar en futuras versiones de Mac OS X.
Valor de retorno:
- Si el receptor y la otra fecha son exactamente iguales entre sí,
NSOrderedSame
- Si el receptor está más tarde que otra fecha,
NSOrderedDescending
- Si el receptor es anterior en el tiempo a otroDate,
NSOrderedAscending
.
Puedes comparar dos fechas por este método también
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;
}
- (NSDate *)earlierDate:(NSDate *)anotherDate
Esto devuelve el anterior del receptor y otra fecha. Si ambos son iguales, se devuelve el receptor.