Question

Comment calculer le nombre de mois entre deux dates à l'aide de cacao?

Merci, Stan

Était-ce utile?

La solution

Regardez NSCalendars Composants: FREST: TODATE: OPTIONS méthode. Il vous permet de soustraire les dates, puis d'extraire la valeur de la propriété des mois

Autres conseils

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

Pour obtenir une réponse qui comprend la fraction d'un mois ce qui suit peut être utilisée:

- (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)]; 
}

J'ai dû calculer les mois de changements entre deux dates. Cela signifie que du 31 janvier au 1er février, le 1er mois s'est écoulé était NSCalendar.components retournera 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!")
    }
}

Composants: FRODDATE: TODATE: Les options ne fonctionnent pas correctement pour l'exemple suivant:

Date de début: 01 janvier 2012 Date de fin: 31 mars 2012.

Num de mois en utilisant la méthode ci-dessus = 2

La bonne réponse doit être de 3 mois.

J'utilise le long chemin des calculs comme suit: 1. Trouvez le nombre de jours au cours du mois de début. Ajoutez-le à la partie fraction du mois. Si la première date est le début du mois, comptez-la comme un mois complet. 2. Trouvez le nombre de jours dans le mois de fin. Ajoutez-le à la partie de la fraction du mois de la date est le dernier du mois, comptez-le comme un mois complet. 3. Trouvez les mois entiers / complets entre les 2 dates et ajoutez à la partie entière du mois. 4. Ajoutez les parties entières et de fraction des mois pour obtenir une valeur correcte.

Voici la version Objective-C de @eliocs Réponse mise à jour pour 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);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top