Como posso calcular a diferença entre duas datas?

115

Como posso calcular os dias entre 1º de janeiro de 2010 e (por exemplo) 3 de fevereiro de 2010?

Frederik Heyninck
fonte

Respostas:

237
NSDate *date1 = [NSDate dateWithString:@"2010-01-01 00:00:00 +0000"];
NSDate *date2 = [NSDate dateWithString:@"2010-02-03 00:00:00 +0000"];

NSTimeInterval secondsBetween = [date2 timeIntervalSinceDate:date1];

int numberOfDays = secondsBetween / 86400;

NSLog(@"There are %d days in between the two dates.", numberOfDays);

EDITAR:

Lembre-se de que os NSDateobjetos representam momentos exatos de tempo, eles não têm nenhuma informação de fuso horário associada. Quando você converte uma string em uma data usando, por exemplo NSDateFormatter, um , o NSDateFormatterconverte a hora do fuso horário configurado. Portanto, o número de segundos entre dois NSDateobjetos sempre será independente do fuso horário.

Além disso, esta documentação especifica que a implementação do tempo do Cocoa não leva em conta os segundos bissextos, portanto, se você precisar de tal precisão, precisará fazer sua própria implementação.

dreamlax
fonte
5
@RalucaGurau: 86400 é o número de segundos em um dia (ou seja, 60 segundos, vezes 60 minutos, vezes 24 horas). Não tem nada a ver com o mês.
dreamlax
18
Nem todos os dias têm 86400 segundos. Para um exemplo trivial, tudo bem, mas não é uma boa ideia no mundo real. Mudanças de horário de verão, segundos bissextos, etc. podem bagunçar tudo. O NSCalendar pode informar quantos segundos faltam em um determinado dia.
NeilInglis
2
@muthukumar: Não no iOS, o método está disponível apenas no Mac OS X. Esta pergunta está marcada cocoae não, cocoa-touchportanto, esta resposta se aplica apenas ao Mac OS X.
dreamlax
1
O número de dias entre quaisquer dois momentos no tempo será sempre 86400. Se os humanos estão no estágio de se enganar para acordar uma hora mais cedo do que o normal ou não, não faz diferença para o fato de que um dia tem 86400 segundos de duração (ignorando o salto segundos)
dreamlax
1
Só quero adicionar que se você não tiver aquele +0000 no final, você receberá datas nulas e um valor de 0 sempre na diferença, não importa o que aconteça. Portanto, não caia nessa armadilha.
Volomike
84

Você pode querer usar algo assim:

NSDateComponents *components;
NSInteger days;

components = [[NSCalendar currentCalendar] components: NSDayCalendarUnit 
        fromDate: startDate toDate: endDate options: 0];
days = [components day];

Acredito que esse método é responsável por situações como datas que abrangem uma mudança no horário de verão.

Casey Fleser
fonte
2
existe uma maneira simples de ignorar também a hora para as datas fornecidas?
Mihai Timar,
pode ser alterado de acordo com outras unidades de calendário :) usadas para a unidade de ano.
experiente em tecnologia de
NSDateobjetos já são agnósticos de fuso horário. As informações de fuso horário são removidas ao analisar datas com NSDateFormatter, por exemplo , para que os NSDateobjetos representem momentos exatos no tempo. Portanto, se você já tiver startDatee endDate, esses dois objetos terão um intervalo de x segundos. Os fusos horários não terão nada a ver com isso.
dreamlax
@Benjamin: Por que você diz isso?
dreamlax
dreamlax, sua resposta está errada. Claro e simples. Calcule o número de dias entre o meio-dia de 1º de janeiro e o horário de verão ao meio-dia de 1º de abril e sua fórmula não funcionará. É uma fórmula preguiçosa e os desenvolvedores devem usar o objeto NSDateComponents para calcular isso.
Rickster,
25
NSTimeInterval diff = [date2 timeIntervalSinceDate:date1]; // in seconds

onde date1edate2 estãoNSDate .

Além disso, observe a definição de NSTimeInterval:

typedef double NSTimeInterval;
Chetan
fonte
Observe que NSTimeInterval é realmente um double, então você pode usá-lo como qualquer outro número.
Kendall Helmstetter Gelner
19

Verifique isso. Ele cuida do horário de verão, ano bissexto, pois usa o calendário iOS para calcular. Você pode alterar a string e as condições para incluir minutos com horas e dias.

+(NSString*)remaningTime:(NSDate*)startDate endDate:(NSDate*)endDate
{
    NSDateComponents *components;
    NSInteger days;
    NSInteger hour;
    NSInteger minutes;
    NSString *durationString;

    components = [[NSCalendar currentCalendar] components: NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute fromDate: startDate toDate: endDate options: 0];

    days = [components day];
    hour = [components hour];
    minutes = [components minute];

    if(days>0)
    {
        if(days>1)
            durationString=[NSString stringWithFormat:@"%d days",days];
        else
            durationString=[NSString stringWithFormat:@"%d day",days];
        return durationString;
    }
    if(hour>0)
    {        
        if(hour>1)
            durationString=[NSString stringWithFormat:@"%d hours",hour];
        else
            durationString=[NSString stringWithFormat:@"%d hour",hour];
        return durationString;
    }
    if(minutes>0)
    {
        if(minutes>1)
            durationString = [NSString stringWithFormat:@"%d minutes",minutes];
        else
            durationString = [NSString stringWithFormat:@"%d minute",minutes];

        return durationString;
    }
    return @""; 
}
Jain Ankish
fonte
este método é a maneira perfeita de calcular a diferença de tempo.
Moxarth
apenas você pode manter elseif com todas essas condições if. caso contrário, você obterá apenas um formato de hora mostrado.
Moxarth de
3

Com o Swift 5 e iOS 12, de acordo com suas necessidades, você pode usar uma das duas maneiras a seguir para encontrar a diferença entre duas datas em dias.


# 1. Usando Calendaro dateComponents(_:from:to:)método de

import Foundation

let calendar = Calendar.current

let startDate = calendar.date(from: DateComponents(year: 2010, month: 11, day: 22))!
let endDate = calendar.date(from: DateComponents(year: 2015, month: 5, day: 1))!

let dateComponents = calendar.dateComponents([Calendar.Component.day], from: startDate, to: endDate)

print(dateComponents) // prints: day: 1621 isLeapMonth: false
print(String(describing: dateComponents.day)) // prints: Optional(1621)

# 2. Usando DateComponentsFormattero string(from:to:)método de

import Foundation

let calendar = Calendar.current

let startDate = calendar.date(from: DateComponents(year: 2010, month: 11, day: 22))!
let endDate = calendar.date(from: DateComponents(year: 2015, month: 5, day: 1))!

let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.allowedUnits = [NSCalendar.Unit.day]

let elapsedTime = formatter.string(from: startDate, to: endDate)
print(String(describing: elapsedTime)) // prints: Optional("1,621 days")
Imanou Petit
fonte
1

Swift 4
Experimente e veja (intervalo de datas com String):

// Start & End date string
let startingAt = "01/01/2018"
let endingAt = "08/03/2018"

// Sample date formatter
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy"

// start and end date object from string dates
var startDate = dateFormatter.date(from: startingAt) ?? Date()
let endDate = dateFormatter.date(from: endingAt) ?? Date()


// Actual operational logic
var dateRange: [String] = []
while startDate <= endDate {
    let stringDate = dateFormatter.string(from: startDate)
    startDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate) ?? Date()
    dateRange.append(stringDate)
}

print("Resulting Array - \(dateRange)")

Swift 3

var date1 = Date(string: "2010-01-01 00:00:00 +0000")
var date2 = Date(string: "2010-02-03 00:00:00 +0000")
var secondsBetween: TimeInterval = date2.timeIntervalSince(date1)
var numberOfDays: Int = secondsBetween / 86400
print(numberOfDays)
Krunal
fonte
Nem todos os dias têm essa quantidade de segundos.
Pavan
@Pavan - Você é bem-vindo para compartilhar suas contribuições, atualizando esta resposta e torná-la melhor.
Krunal
Para torná-lo melhor, seria necessário reescrever toda a sua resposta; nesse caso, ela também pode ser excluída, porque será a mesma solução da resposta acima, que não usa valores codificados permanentemente :)
Pavan
0

Você pode encontrar a diferença convertendo a data em segundos e tomar o intervalo de tempo desde 1970 para isso e então você pode encontrar a diferença entre duas datas.

Himanshu Bhatia
fonte
quando duas datas podem ser calculadas diretamente entre si (assumindo o mesmo domínio de tempo). Existe alguma razão específica para calcular ambas as datas desde 1970 primeiro e depois encontrar a diferença?
Adeel de
0

Para encontrar a diferença, você precisa obter a data atual e a data futura. No caso a seguir, usei 2 dias como um exemplo da data futura. Calculado por:

2 days* 24 hours* 60 minutes* 60 seconds. Esperamos que o número de segundos em 2 dias seja de 172.800.

// Set the current and future date
let now = Date()
let nowPlus2Days = Date(timeInterval: 2*24*60*60, since: now)

// Get the number of seconds between these two dates
let secondsInterval = DateInterval(start: now, end: nowPlus2Days).duration

print(secondsInterval) // 172800.0
Roi Zakai
fonte
1
Por favor, não poste apenas código como uma resposta, mas também forneça uma explicação sobre o que seu código faz e como ele resolve o problema da questão. As respostas com uma explicação geralmente são de qualidade superior e têm maior probabilidade de atrair votos positivos.
Mark Rotteveel,