Pregunta

¿Cómo calculo el número de meses entre dos fechas que usan cacao?

Gracias Stan

¿Fue útil?

Solución

Mira nscalendars Componentes: Front Date: Todate: Opciones método. Le permite restablecer las fechas y luego extraer el valor de la propiedad de los meses

Otros consejos

NSInteger month = [[[NSCalendar currentCalendar] components: NSCalendarUnitMonth
                                                   fromDate: yourFirstDate
                                                     toDate: yourSecondDate
                                                    options: 0] month];

Para obtener una respuesta que incluya la fracción de un mes, se puede usar la siguiente:

- (NSNumber *)numberOfMonthsBetweenFirstDate:(NSDate *)firstDate secondDate:(NSDate *)secondDate {

if ([firstDate compare:secondDate] == NSOrderedDescending) {
    return nil;
}

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDateComponents *firstDateComponents = [calendar components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit
                                                    fromDate:firstDate];

NSInteger firstDay = [firstDateComponents day];

NSRange rangeOfFirstMonth = [calendar rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:firstDate];
NSUInteger numberOfDaysInFirstMonth = rangeOfFirstMonth.length;
CGFloat firstMonthFraction = (CGFloat)(numberOfDaysInFirstMonth - firstDay) / (CGFloat)numberOfDaysInFirstMonth;

// last month component
NSDateComponents *lastDateComponents = [calendar components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit
                                                              fromDate:secondDate];
NSInteger lastDay = [lastDateComponents day];
NSRange rangeOfLastMonth = [calendar rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:secondDate];
NSUInteger numberOfDaysInLastMonth = rangeOfLastMonth.length;
CGFloat lastMonthFraction = (CGFloat)(lastDay) / (CGFloat)numberOfDaysInLastMonth;

// Check if the two dates are within the same month
if (firstDateComponents.month == lastDateComponents.month
        && firstDateComponents.year == lastDateComponents.year) {
    NSDateComponents *dayComponents = [calendar components:NSDayCalendarUnit
                                                           fromDate:firstDate
                                                             toDate:secondDate
                                                            options:0];

    NSRange rangeOfMonth = [calendar rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:firstDate];
    NSUInteger numberOfDaysInMonth = rangeOfMonth.length;
    return [NSNumber numberWithFloat:(CGFloat)dayComponents.day / (CGFloat)numberOfDaysInMonth];
}

//  Start date of the first complete month
NSDateComponents *firstDateFirstDayOfNextMonth = firstDateComponents;
firstDateFirstDayOfNextMonth.month +=1;
firstDateFirstDayOfNextMonth.day = 1;

// First day of the last month
NSDateComponents *secondDateFirstDayOfMonth = lastDateComponents;
secondDateFirstDayOfMonth.day = 1;

NSInteger numberOfMonths = secondDateFirstDayOfMonth.month - firstDateFirstDayOfNextMonth.month
        + (secondDateFirstDayOfMonth.year - firstDateFirstDayOfNextMonth.year) * 12;

return [NSNumber numberWithFloat:(firstMonthFraction + numberOfMonths + lastMonthFraction)]; 
}

Tuve que calcular los cambios de los meses entre dos fechas. Esto significa que desde el 31 de enero hasta el 1 del 1 mes de febrero ha pasado fueron NSCalendar.components Volverá 0.

import UIKit

func monthsSince(from: NSDate, to: NSDate) -> Int {
    let fromComponents = NSCalendar.currentCalendar().components([.Month, .Year], fromDate: from)
    let toComponents = NSCalendar.currentCalendar().components([.Month, .Year], fromDate: to)

    return ((toComponents.year - fromComponents.year) * 12) + (toComponents.month - fromComponents.month)
}

let tests = [
    (from: (day: 1, month: 1, year: 2016), to: (day: 31, month: 1, year: 2016), result: 0),
    (from: (day: 22, month: 1, year: 2016), to: (day: 5, month: 2, year: 2016), result: 1),
    (from: (day: 22, month: 12, year: 2015), to: (day: 1, month: 1, year: 2016), result: 1),
    (from: (day: 1, month: 1, year: 2016), to: (day: 1, month: 2, year: 2016), result: 1),
    (from: (day: 1, month: 1, year: 2016), to: (day: 1, month: 3, year: 2016), result: 2)
]

for test in tests {
    let from = NSCalendar.currentCalendar().dateWithEra(1, year: test.from.year, month: test.from.month, day: test.from.day, hour: 0, minute: 0, second: 0, nanosecond: 0)!
    let to = NSCalendar.currentCalendar().dateWithEra(1, year: test.to.year, month: test.to.month, day: test.to.day, hour: 0, minute: 0, second: 0, nanosecond: 0)!

    if monthsSince(from, to: to) == test.result {
        print("Test \(test), Passed!")
    } else {
        print("Test \(test), Failed!")
    }
}

Componentes: Front Date: Todate: Las opciones no funcionan correctamente para el siguiente ejemplo:

Fecha de inicio: 01 de enero de 2012 Fecha de finalización: 31 de marzo de 2012.

Número de meses utilizando el método anterior = 2

La respuesta correcta debe ser de 3 meses.

Estoy usando la larga forma de cálculos de la siguiente manera: 1. Encuentre el número de días en el mes inicial. Agrégalo a la parte de la fracción del mes. Si la primera cita es el comienzo del mes, cuente como un mes completo. 2. Encuentre el número de días al final del mes. Agrégalo a la parte de la fracción del mes si la fecha es la última del mes lo cuenta como un mes completo. 3. Encuentre los meses completos/completos entre las 2 fechas y agregue a la parte entera del mes. 4. Agregue las partes enteras y de fracción de los meses para obtener un valor correcto.

Aquí está la versión Objective-C de la respuesta @ElioCs actualizada para iOS11:

- (NSInteger)monthsSince:(NSDate *)from to:(NSDate *)to {
    NSDateComponents *fromComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitMonth | NSCalendarUnitYear fromDate:from];
    NSDateComponents *toComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitMonth | NSCalendarUnitYear fromDate:to];

    return ((toComponents.year - fromComponents.year) * 12) + (toComponents.month - fromComponents.month);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top