2009-09-24 7 views

Répondre

5

Si vous n'utilisez que le calendrier grégorien, vous pouvez le calculer manuellement.

http://en.wikipedia.org/wiki/Leap_year#Algorithm

if year modulo 400 is 0 then leap 
else if year modulo 100 is 0 then no_leap 
else if year modulo 4 is 0 then leap 
else no_leap 
+2

Calculer les jours dans l'année est assez simple, mais en général, je recommande d'aller avec les bibliothèques de date/heure disponibles. Faire des calculs de date/heure manuellement reviendra toujours et vous mordra en quelque sorte ... – Krumelur

+0

Je recommande fortement contre cela. Le temps est super compliqué. Si vous avez besoin de votre matériel pour travailler dans d'autres lieux qui ne pourraient pas utiliser le calendrier grégorien ou qui ont besoin de travailler dans un passé lointain (encore une fois pas grégorien) cela ne fonctionnera pas. NSCalendar est génial pour résoudre ce genre de choses. –

5

Je suis finalement arrivé avec une solution qui fonctionne. Ce que je fais est d'abord calculer le nombre de mois dans l'année et puis pour chaque mois, calculer le nombre de jours pour ce mois.

Le code ressemble à ceci:

NSUInteger days = 0; 
NSCalendar *calendar = [NSCalendar currentCalendar]; 
NSDate *today = [NSDate date]; 
NSDateComponents *components = [calendar components:NSYearCalendarUnit fromDate:today]; 
NSUInteger months = [calendar rangeOfUnit:NSMonthCalendarUnit 
            inUnit:NSYearCalendarUnit 
            forDate:today].length; 
for (int i = 1; i <= months; i++) { 
    components.month = i; 
    NSDate *month = [calendar dateFromComponents:components]; 
    days += [calendar rangeOfUnit:NSDayCalendarUnit 
          inUnit:NSMonthCalendarUnit 
          forDate:month].length; 
} 

return days; 

Il est pas aussi propre que je l'aurais espéré, mais cela fonctionnera pour tout calendrier tel que le grégorienne ordinaire ou celui islamic.

1

Utilisez les classes NSCalendar et NSDateComponent, comme celui-ci:

long GetDaysInYear(int year) { 
    NSDateComponents* c = [[NSDateComponents alloc] init]; 
    c.year = year; 
    NSCalendar* cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
    NSDate* startDate = [cal dateFromComponents:c]; 
    c.year += 1; 
    NSDate* endDate = [cal dateFromComponents:c]; 
    return [cal components:NSDayCalendarUnit fromDate:startDate toDate:endDate options:0].day; 
} 
0

A titre d'exemple:

func daysInYear(year: Int) -> Int { 
    var calendar = NSCalendar(calendarIdentifier: NSGregorianCalendar) 
    var b = NSDate.dateWithNaturalLanguageString("01.01.\(year)", locale: NSLocale.currentLocale()) as! NSDate 
    var e = NSDate.dateWithNaturalLanguageString("12.31.\(year)", locale: NSLocale.currentLocale()) as! NSDate 

    return calendar!.components(NSCalendarUnit.CalendarUnitDay, fromDate: b, toDate: e, options: nil).day + 1 
} 

Mais les jours par défaut reviennent 355 et 354 a fait subir (peut-être) que le comptage commence à partir de zéro:

+0

C'est un de moins depuis que vous commencez dès le premier jour. Si vous faites du 31/12 au 31/12, c'est une année complète :) –

+0

Je pense que l'année a commencé à partir du 01.01.2015 00:00:00 (000) et terminé au 31.12.2015 23:59:59 (99) :)) – iTux

8

Voici une extension NSCalendar super précise dans Swift 2:

extension NSCalendar { 
    func daysInYear(date: NSDate = NSDate()) -> Int? { 
     let year = components([NSCalendarUnit.Year], fromDate: date).year 
     return daysInYear(year) 
    } 

    func daysInYear(year: Int) -> Int? { 
     guard let begin = lastDayOfYear(year - 1), end = lastDayOfYear(year) else { return nil } 
     return components([NSCalendarUnit.Day], fromDate: begin, toDate: end, options: []).day 
    } 

    func lastDayOfYear(year: Int) -> NSDate? { 
     let components = NSDateComponents() 
     components.year = year 
     guard let years = dateFromComponents(components) else { return nil } 

     components.month = rangeOfUnit(NSCalendarUnit.Month, inUnit: NSCalendarUnit.Year, forDate: years).length 
     guard let months = dateFromComponents(components) else { return nil } 

     components.day = rangeOfUnit(NSCalendarUnit.Day, inUnit: NSCalendarUnit.Month, forDate: months).length 

     return dateFromComponents(components) 
    } 
} 

Vous pouvez l'utiliser comme ceci:

let calendar = NSCalendar.currentCalendar() // I'm using the Gregorian calendar 
calendar.daysInYear()  // 365 (since it's currently 2015) 
calendar.daysInYear(2016) // 366 (leap year!) 

C'est super flexible puisque nous ne supposons rien sur la longueur du calendrier:

let hebrew = NSCalendar(calendarIdentifier: NSCalendarIdentifierHebrew) 
hebrew?.daysInYear(-7) // 354 
hebrew?.daysInYear(-100) // 384 

Profitez.

+0

Une autre approche serait d'obtenir les mois dans l'année donnée, puis d'énumérer chaque mois et additionner les jours. Je ne suis pas sûr de ce qui est le plus précis ou le plus efficace. Je suppose que mon approche actuelle est la plus efficace. Aucune idée si c'est plus précis de le faire dans l'autre sens. Le temps est dur. –

Questions connexes