Determinare il numero di mesi tra due date utilizzando cacao
-
18-09-2019 - |
Domanda
Come faccio a calcolare il numero di mesi tra due date utilizzando Cocoa?
Grazie, Stan
Soluzione
Guarda NSCalendars componenti: fromdate: tODATE: opzioni metodo. Esso consente di sottrarre date e poi estrarre il valore della proprietà mesi
Altri suggerimenti
NSInteger month = [[[NSCalendar currentCalendar] components: NSCalendarUnitMonth
fromDate: yourFirstDate
toDate: yourSecondDate
options: 0] month];
Per ottenere una risposta che include la frazione di un mese, i seguenti può essere utilizzato:
- (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)];
}
Ho dovuto calcolare i mesi cambiamenti tra due date. Ciò significa che dal 31 gennaio al 1 ° febbraio 1 mese è passato erano NSCalendar.components
restituirà 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!")
}
}
componenti: fromdate: TODATE: opzioni non funziona correttamente per esempio seguente:
Data inizio: 1 Gennaio 2012 Data fine:. 31 MARZO 2012
num di mesi utilizzando sopra method = 2
La risposta corretta dovrebbe essere di 3 mesi.
Sono utilizzando la lunga strada dei calcoli come segue: 1. Trovare il numero di giorni del mese a partire. Aggiungere alla parte frazionaria del mese. Se la prima data è l'inizio del mese, ritengo che il mese intero. 2. trovare il numero di giorni nel mese finale. Aggiungere alla parte frazionaria del monthIf la data è l'ultimo del mese, conta come un mese intero. 3. Trovare l'intero / full mesi tra le 2 date e aggiungere alla parte intera del mese. 4. Aggiungere i numeri interi e frazioni dei mesi per ottenere un valore corretto.
Ecco la versione Objective-C di @eliocs rispuose aggiornata per 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);
}