iOS: compare duas datas

96

Eu tenho um NSDateque devo comparar com os outros dois NSDatee tento com NSOrderAscendinge NSOrderDescendingmas se minha data for igual nas outras duas datas?

Exemplo: se eu tiver um myDate = 24/05/2011 e outros dois que são um = 24/05/2011e dois, o 24/05/2011que posso usar?

cyclingIsBetter
fonte
1
Não entendi totalmente sua pergunta, o que você está tentando alcançar?
arco voltaico
a data um e a data dois podem ser um = 15/05/2011 e dois = 31/05/2011 mas devem ser também o mesmo dia um = 24/05/2011 e dois = 24/05/2011, então devo verificar se myData está entre as datas um e dois
cyclingIsBetter
Extraia o ano, o mês e a data e compare-os nessa ordem. Se houver empate, compare o próximo campo.
Himadri Choudhury

Respostas:

210

De acordo com a documentação da Apple deNSDate compare:

Retorna um valor NSComparisonResult que indica a ordem temporal do receptor e outra data especificada.

- (NSComparisonResult)compare:(NSDate *)anotherDate

Parâmetros anotherDate

A data com a qual comparar o receptor. Este valor não deve ser nulo. Se o valor for nulo, o comportamento é indefinido e pode mudar em versões futuras do Mac OS X.

Valor de retorno

E se:

O receptor e outra data são exatamente iguais, NSOrderedSame

O receptor está atrasado em relação a outra data, NSOrderedDescending

O receptor é anterior a outra data, NSOrderedAscending

Em outras palavras:

if ([date1 compare:date2] == NSOrderedSame) ...

Observe que pode ser mais fácil em seu caso particular ler e escrever isto:

if ([date2 isEqualToDate:date2]) ...

Consulte a documentação da Apple sobre este .

Vincent Guerci
fonte
mas f ([data1 compare: data2] == NSOrderedSame) verifique também a hora, minuto e segundos e eu não quero isso
cyclingIsBetter
1
sua pergunta estava um pouco confusa, desculpe, dê uma olhada em stackoverflow.com/questions/1889164/3092009#3092009 , você encontrará a resposta para isso.
Vincent Guerci
Essa resposta está correta em ambos os sentidos. Para controlar os componentes de data que você está comparando, useNSDateComponents
Nazir
32

Depois de pesquisar muito o stackoverflow e a web, cheguei à conclusão de que a melhor maneira de fazer isso é:

- (BOOL)isEndDateIsSmallerThanCurrent:(NSDate *)checkEndDate
{
    NSDate* enddate = checkEndDate;
    NSDate* currentdate = [NSDate date];
    NSTimeInterval distanceBetweenDates = [enddate timeIntervalSinceDate:currentdate];
    double secondsInMinute = 60;
    NSInteger secondsBetweenDates = distanceBetweenDates / secondsInMinute;

    if (secondsBetweenDates == 0)
        return YES;
    else if (secondsBetweenDates < 0)
        return YES;
    else
        return NO;
}

Você pode alterá-lo para a diferença entre as horas também.

Aproveitar!


Editar 1

Se você quiser comparar a data com o formato de dd / MM / aaaa apenas, você precisa adicionar as linhas abaixo entre NSDate* currentdate = [NSDate date];&&NSTimeInterval distance

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"dd/MM/yyyy"];
[dateFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]
                          autorelease]];

NSString *stringDate = [dateFormatter stringFromDate:[NSDate date]];

currentdate = [dateFormatter dateFromString:stringDate];
Yossi Tsafar
fonte
1
Obrigado, isso funciona melhor do que comparar ou isEqualToDate
ArdenDev
Acordado. Encontrei problemas ao usar compare & isEqualToDate. Claro, podem ser 2 linhas extras de código, mas são mais confiáveis.
Treinador Roebuck
23

Suponho que você esteja perguntando qual é o valor de retorno na função de comparação.

Se as datas forem iguais, retornar NSOrderedSame

Se ascendente (2º argumento> 1º argumento) retornar NSOrderedAscending

Se for decrescente (2º argumento <1º argumento), retorne NSOrderedDescending

Himadri Choudhury
fonte
Boa maneira de pensar em subir e descer.
David
16

Não sei exatamente se você perguntou isso, mas se você deseja apenas comparar o componente de data de um NSDate, você deve usar NSCalendar e NSDateComponents para remover o componente de tempo.

Algo assim deve funcionar como uma categoria para NSDate:

- (NSComparisonResult)compareDateOnly:(NSDate *)otherDate {
    NSUInteger dateFlags = NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit;
    NSCalendar *gregorianCalendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
    NSDateComponents *selfComponents = [gregorianCalendar components:dateFlags fromDate:self];
    NSDate *selfDateOnly = [gregorianCalendar dateFromComponents:selfComponents];

    NSDateComponents *otherCompents = [gregorianCalendar components:dateFlags fromDate:otherDate];
    NSDate *otherDateOnly = [gregorianCalendar dateFromComponents:otherCompents];
    return [selfDateOnly compare:otherDateOnly];
}
Matthias Bauch
fonte
2

NSDatena verdade, representa um intervalo de tempo em segundos desde uma data de referência (primeiro de janeiro de 2000 UTC, eu acho). Internamente, um número de ponto flutuante de precisão dupla é usado para que duas datas arbitrárias sejam altamente improváveis ​​de serem comparadas, mesmo que sejam no mesmo dia. Se você quiser ver se uma determinada data cai em um determinado dia, você provavelmente precisará usar NSDateComponents. por exemplo

NSDateComponents* dateComponents = [[NSDateComponents alloc] init];
[dateComponents setYear: 2011];
[dateComponents setMonth: 5];
[dateComponents setDay: 24];
/*
 *  Construct two dates that bracket the day you are checking.  
 *  Use the user's current calendar.  I think this takes care of things like daylight saving time.
 */
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDate* startOfDate = [calendar dateFromComponents: dateComponents];
NSDateComponents* oneDay = [[NSDateComponents alloc] init];
[oneDay setDay: 1];
NSDate* endOfDate = [calendar dateByAddingComponents: oneDay toDate: startOfDate options: 0];
/*
 *  Compare the date with the start of the day and the end of the day.
 */
NSComparisonResult startCompare = [startOfDate compare: myDate];
NSComparisonResult endCompare = [endOfDate compare: myDate];

if (startCompare != NSOrderedDescending && endCompare == NSOrderedDescending)
{
    // we are on the right date
} 
JeremyP
fonte
2

Verifique a função a seguir para comparação de datas, antes de tudo, crie dois objetos NSDate e passe para a função: Adicione as linhas de código abaixo em viewDidload ou de acordo com seu cenário.

-(void)testDateComaparFunc{

NSString *getTokon_Time1 = @"2016-05-31 03:19:05 +0000";
NSString *getTokon_Time2 = @"2016-05-31 03:18:05 +0000";
NSDateFormatter *dateFormatter=[NSDateFormatter new];
[dateFormatter setDateFormat:@"yyyy-MM-dd hh:mm:ss Z"];
NSDate *tokonExpireDate1=[dateFormatter dateFromString:getTokon_Time1];
NSDate *tokonExpireDate2=[dateFormatter dateFromString:getTokon_Time2];
BOOL isTokonValid = [self dateComparision:tokonExpireDate1 andDate2:tokonExpireDate2];}

aqui está a função

-(BOOL)dateComparision:(NSDate*)date1 andDate2:(NSDate*)date2{

BOOL isTokonValid;

if ([date1 compare:date2] == NSOrderedDescending) {
    //"date1 is later than date2
    isTokonValid = YES;
} else if ([date1 compare:date2] == NSOrderedAscending) {
    //date1 is earlier than date2
    isTokonValid = NO;
} else {
   //dates are the same
    isTokonValid = NO;

}

return isTokonValid;}

Basta alterar a data e testar a função acima :)

Akhtar
fonte