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] rangeOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:[NSDate date]];
but that gives me the number of days in the current month instead of the number of days in the current year.
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.
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];
}
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
I don't know if anybody is still interested in this thread, but is another possible solution:
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *startOfYear;
NSTimeInterval lengthOfYear;
[calendar rangeOfUnit:NSYearCalendarUnit
startDate:&startOfYear
interval:&lengthOfYear
forDate:[NSDate date]];
NSDate *endOfYear = [startOfYear dateByAddingTimeInterval:lengthOfYear];
NSDateComponents *comp = [calendar components:NSDayCalendarUnit
fromDate:startOfYear
toDate:endOfYear
options:0];
NSUInteger numberOfDaysInThisYear = [comp day];
using only 2 calls to NSCalendar
.
Maybe you can use the components:fromDate:toDate:options:
selector which is meant to (and I quote official Apple docs): Returns, as an NSDateComponents object using specified components, the difference between two supplied dates. ?
Also read this post that clarifies the behaviour you are seeing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With