How do I calculate the number of days in this year in Objective C

前端 未结 12 2083
旧巷少年郎
旧巷少年郎 2020-12-06 03:07

How can i calculate the number of days in a year for any calendar, not just gregorian. I have tried this

NSUInteger *days = [[NSCalendar currentCalendar] range

相关标签:
12条回答
  • 2020-12-06 03:58

    In general you may use number of days between 1st day of the year and 1st day of the next year. Here's the code that illustrates this approach

    - (NSDate *)firstDateOfYear:(NSInteger)year
    {
        NSDateComponents *dc = [[NSDateComponents alloc] init];
        dc.year = year;
        dc.month = 1;
        dc.day = 1;
        return [[NSCalendar currentCalendar] dateFromComponents:dc];
    }
    
    - (NSUInteger)numberOfDaysInYear:(NSInteger)year
    {
        NSDate *firstDateOfYear = [self firstDateOfYear:year];
        NSDate *firstDateOfNextYear = [self firstDateOfYear:year + 1];
        NSDateComponents *components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit fromDate:firstDateOfYear toDate:firstDateOfNextYear options:0];
        return [components day];
    }
    
    0 讨论(0)
  • 2020-12-06 03:59

    In order to do what you want you have to find the range of days in a month and months in a year for a specific calendar. This function will do what you need for any calendar that uses day/month/year units (or has some equivalent mapped):

    NSInteger getDaysInYear(NSDate* date)
    {
        // Get the current calendar
        NSCalendar* c = [NSCalendar currentCalendar];
    
        // Find the range for days and months in this calendar
        NSRange dayRange = [c rangeOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:date];
        NSRange monthRange = [c rangeOfUnit:NSMonthCalendarUnit inUnit:NSYearCalendarUnit forDate:date];
    
        // Get the year from the suppled date
        NSDateComponents* yearComps = [c components:NSYearCalendarUnit fromDate:date];
        NSInteger thisYear = [yearComps year];
    
        // Create the first day of the year in the current calendar
        NSUInteger firstDay = dayRange.location;
        NSUInteger firstMonth = monthRange.location;
        NSDateComponents* firstDayComps = [[[NSDateComponents alloc] init] autorelease];
        [firstDayComps setDay:firstDay];
        [firstDayComps setMonth:firstMonth];
        [firstDayComps setYear:thisYear];
        NSDate* firstDayDate = [c dateFromComponents:firstDayComps];
    
        // Create the last day of the year in the current calendar
        NSUInteger lastDay = dayRange.length;
        NSUInteger lastMonth = monthRange.length;
        NSDateComponents* lastDayComps = [[[NSDateComponents alloc] init] autorelease];
        [lastDayComps setDay:lastDay];
        [lastDayComps setMonth:lastMonth];
        [lastDayComps setYear:thisYear];
        NSDate* lastDayDate = [c dateFromComponents:lastDayComps];
    
        // Find the difference in days between the first and last days of the year
        NSDateComponents* diffComps = [c components:NSDayCalendarUnit 
                                           fromDate:firstDayDate
                                             toDate:lastDayDate
                                            options:0];
    
        // We have to add one since this was subtraction but we really want to
        // give the total days in the year
        return [diffComps day] + 1;
    }
    

    If you want to specify this year, you can call it simply as getDaysInYear([NSDate date]);, or you could create a date from specific year/other components and pass that. You could also very easily re-implement it as a method call.

    0 讨论(0)
  • 2020-12-06 04:00

    I don't know objective-c but it is a simple algorithm to determine if it is a leap year.

    if ( year % 400 == 0 )
       then 366 // Leap Year
    else if ( year % 100 == 0 )
       then 365 // Non-Leap Year
    else if ( year % 4 == 0 )
       then 366 // Leap Year
    else
       365 // Non-Leap Year
    

    Or if you want a little less verbose version

    if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))
       then 366 // Leap Year
    else
       365 // Non-Leap Year
    
    0 讨论(0)
  • 2020-12-06 04:03

    Best solution found for this problem using SWIFT 5.3 and Xcode 12.

    Put it into playgrounds, call the checkLeapYear function passing a year into it and play around.

    func checkLeapYear(year: Int) {
        if year % 4 == 0{
            if year % 100 == 0 {
                if year % 400 == 0{
                    print("\(year) is a Leap Year!")
                } else {
                    print("\(year) is NOT a Leap Year!")
                }
            } else {
                print("\(year) is a Leap Year!")
            }
        } else {
            print("\(year) is NOT a Leap Year!")
        }
    }
    

    The algorithm is quite tricky so I suggest you use the following logic when performing it on your own:

    1. If the year is evenly divisible by 4, go to step 2. Otherwise, go to step 5.
    2. If the year is evenly divisible by 100, go to step 3. Otherwise, go to step 4.
    3. If the year is evenly divisible by 400, go to step 4. Otherwise, go to step 5.
    4. The year is a leap year.
    5. The year is not a leap year.
    0 讨论(0)
  • 2020-12-06 04:04

    I finally came up with a solution that works. What I do is first calculate the number of months in the year and then for each month calculate the number of days for that month.

    The code looks like this:

    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;
    

    It is not as neat as I would have hoped for but it will work for any calendar such as the ordinary gregorian one or the islamic one.

    0 讨论(0)
  • 2020-12-06 04:08
    [[NSCalendar currentCalendar] ordinalityOfUnit:NSYearCalendarUnit
                                            inUnit:NSEraCalendarUnit forDate:date];
    
    0 讨论(0)
提交回复
热议问题