¿Cómo puedo calcular la diferencia entre dos fechas?

115

¿Cómo puedo calcular los días entre el 1 de enero de 2010 y (por ejemplo) el 3 de febrero de 2010?

Frederik Heyninck
fuente

Respuestas:

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:

Recuerde, los NSDateobjetos representan momentos exactos de tiempo, no tienen ninguna información de zona horaria asociada. Cuando convierte una cadena en una fecha usando, por ejemplo NSDateFormatter, an , NSDateFormatterconvierte la hora de la zona horaria configurada. Por lo tanto, el número de segundos entre dos NSDateobjetos siempre será independiente de la zona horaria.

Además, esta documentación especifica que la implementación del tiempo de Cocoa no tiene en cuenta los segundos intercalares, por lo que si necesita tal precisión, deberá implementar su propia implementación.

Dreamlax
fuente
5
@RalucaGurau: 86400 es el número de segundos en un día (es decir, 60 segundos, multiplicado por 60 minutos, multiplicado por 24 horas). No tiene nada que ver con el mes.
dreamlax
18
No todos los días tienen 86400 segundos. Para un ejemplo trivial, está bien, pero no es una buena idea en el mundo real. Los cambios de horario de verano, los segundos intercalares, etc. pueden afectarlo. NSCalendar puede decirle cuántos segundos hay en un día determinado.
NeilInglis
2
@muthukumar: no en iOS, el método solo está disponible en Mac OS X. Esta pregunta está etiquetada cocoay no, cocoa-touchpor lo que esta respuesta solo se aplica a Mac OS X.
dreamlax
1
El número de días entre dos momentos en el tiempo siempre será 86400. Si los humanos están en la etapa de engañarse a sí mismos para despertarse una hora antes de lo normal o no, no importa el hecho de que un día dura 86400 segundos (ignorando el salto segundos)
dreamlax
1
Solo quiero agregar que si no tiene ese +0000 al final, obtendrá fechas nulas y un valor de 0 siempre en la diferencia, sin importar qué. Entonces, no caigas en esa trampa.
Volomike
84

Es posible que desee utilizar algo como esto:

NSDateComponents *components;
NSInteger days;

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

Creo que este método tiene en cuenta situaciones como las fechas que abarcan un cambio en el horario de verano.

Casey Fleser
fuente
2
¿Existe una forma sencilla de ignorar también la hora de las fechas dadas?
Mihai Timar
se puede cambiar en consecuencia para otras unidades de calendario :) utilizadas para la unidad de año.
experto en tecnología
NSDatelos objetos ya son independientes de la zona horaria. La información de la zona horaria se elimina al analizar las fechas con NSDateFormatter, por ejemplo , para que los NSDateobjetos representen momentos exactos en el tiempo. Por lo tanto, si ya tiene startDatey endDate, estos dos objetos estarán separados por x segundos. Las zonas horarias no tendrán nada que ver con eso.
dreamlax
@Benjamin: ¿Por qué dices eso?
dreamlax
dreamlax, tu respuesta es incorrecta. Simple y llanamente. Calcule la cantidad de días entre las 12 del mediodía, hora estándar del 1 de enero, y las 12 del mediodía, hora de verano del 1 de abril, y su fórmula no funcionará. Es una fórmula perezosa y los desarrolladores deben usar el objeto NSDateComponents para calcular esto.
Rickster
25
NSTimeInterval diff = [date2 timeIntervalSinceDate:date1]; // in seconds

donde date1y date2son NSDate.

Además, tenga en cuenta la definición de NSTimeInterval:

typedef double NSTimeInterval;
Chetan
fuente
Tenga en cuenta que NSTimeInterval es realmente un doble, por lo que puede usarlo como cualquier otro número.
Kendall Helmstetter Gelner
19

Mira esto. Se encarga del horario de verano, año bisiesto, ya que usó el calendario de iOS para calcular. Puede cambiar la cadena y las condiciones para incluir minutos con horas y días.

+(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 @""; 
}
Ankish Jain
fuente
este método es la forma perfecta de calcular la diferencia horaria.
Moxarth
solo puedes quedarte elseif con todas esas condiciones if. de lo contrario, solo se mostrará un formato de hora.
Moxarth
3

Con Swift 5 y iOS 12, según sus necesidades, puede usar una de las dos formas siguientes para encontrar la diferencia entre dos fechas en días.


# 1. Usando Calendarel 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 DateComponentsFormatterel 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
fuente
1

Swift 4
Pruebe esto y vea (rango de fechas con 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
fuente
No todos los días tienen esa cantidad de segundos.
Pavan
@Pavan: le invitamos a compartir sus aportaciones actualizando esta respuesta y mejorandola.
Krunal
Para mejorarlo, sería necesario que reescribiera toda su respuesta, en cuyo caso también podría eliminarse porque será la misma solución que la respuesta anterior, que no usa valores codificados :)
Pavan
0

Puede encontrar la diferencia convirtiendo la fecha en segundos y tomar el intervalo de tiempo desde 1970 para esto y luego puede encontrar la diferencia entre dos fechas.

Himanshu Bhatia
fuente
cuando dos fechas se pueden calcular directamente entre sí (asumiendo el mismo dominio de tiempo). ¿Existe alguna razón específica para calcular ambas fechas desde 1970 primero y luego encontrar la diferencia?
Adeel
0

Para encontrar la diferencia, debe obtener la fecha actual y la fecha futura. En el siguiente caso, utilicé 2 días como ejemplo de la fecha futura. Calculado por:

2 days* 24 hours* 60 minutes* 60 seconds. Esperamos que la cantidad de segundos en 2 días sea 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
fuente
1
No publique solo el código como respuesta, sino que también proporcione una explicación de lo que hace su código y cómo resuelve el problema de la pregunta. Las respuestas con una explicación suelen ser de mayor calidad y es más probable que atraigan votos positivos.
Mark Rotteveel