2009-09-24 15 views

Odpowiedz

5

Jeśli zamierzasz używać kalendarza gregoriańskiego, możesz obliczyć go ręcznie.

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

Obliczanie dni w roku jest dość proste, ale ogólnie polecam iść z dostępnymi bibliotekami daty/czasu. Ręczne wykonywanie obliczeń daty/czasu zawsze będzie zawsze wracać i cię kąsać ... – Krumelur

+0

Zdecydowanie polecam przeciw temu. Czas jest bardzo skomplikowany. Jeśli potrzebujesz swoich rzeczy do pracy w innych miejscach, które mogą nie używać kalendarza gregoriańskiego lub musisz pracować w odległej przeszłości (znowu nie gregoriański), to nie zadziała. NSCalendar jest świetny do rozwiązywania takich problemów. –

5

I wreszcie wymyślił rozwiązanie, które działa. To, co robię, to najpierw obliczyć liczbę miesięcy w roku, a następnie dla każdego miesiąca obliczyć liczbę dni dla tego miesiąca.

Kod wygląda następująco:

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; 

To nie jest tak czysty, jak bym się spodziewać, ale to będzie działać na każdym kalendarzu, takich jak zwykłą gregoriański jednego lub islamski jeden.

1

Użyj NSCalendar i NSDateComponent zajęcia, na przykład:

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

Jako przykład:

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 
} 

Ale domyślne dzień powrotu 355 i 354 to spowodowane (może być), że liczenie rozpoczyna się od zera:)

+0

To o jeden mniej, odkąd zaczynasz od pierwszego dnia. Jeśli robisz od 12/31 do 12/31, to jest cały rok :) –

+0

Myślę, że rok zaczął się od 01.01.2015 00:00:00 (000) i zakończył się 31.12.2015 23:59:59 (99) :)) – iTux

8

Oto super dokładne rozszerzenie NSCalendar w 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) 
    } 
} 

Można go używać tak:

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

Jest to bardzo elastyczne, ponieważ nie wiemy nic o długości kalendarzu zakładają:

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

cieszyć.

+0

Innym podejściem byłoby uzyskanie miesięcy w danym roku, a następnie wyliczenie każdego miesiąca i sumowanie dni. Nie jestem pewien, który jest dokładniejszy lub bardziej wydajny. Zakładam, że moje obecne podejście jest najbardziej wydajne. Nie mam pojęcia, czy dokładniej zrobić to w drugą stronę. Czas jest trudny. –

Powiązane problemy