Как рассчитать количество дней в этом году в Задаче C - PullRequest
5 голосов
/ 16 января 2010

Как рассчитать количество дней в году для любого календаря, а не только для григорианского Я пробовал это

NSUInteger *days = [[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:[NSDate date]];

но это дает мне количество дней в текущем месяце вместо количества дней в текущем году.

Ответы [ 11 ]

10 голосов
/ 16 января 2010

Я наконец-то нашел решение, которое работает.Сначала я вычисляю количество месяцев в году, а затем для каждого месяца вычисляю количество дней в этом месяце.

Код выглядит следующим образом:

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;

Этоне так аккуратно, как я бы надеялся, но он будет работать для любого календаря, такого как обычный григорианский или исламский.

8 голосов
/ 20 ноября 2012

Как правило, вы можете использовать количество дней между 1-м днем ​​года и 1-м днем ​​следующего года. Вот код, который иллюстрирует этот подход

- (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];
}
3 голосов
/ 16 января 2010

Я не знаю target-c, но это простой алгоритм, чтобы определить, является ли это високосным годом.

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

Или, если вы хотите немного менее подробную версию

if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))
   then 366 // Leap Year
else
   365 // Non-Leap Year
2 голосов
/ 29 мая 2013

Я не знаю, заинтересован ли кто-либо еще в этой теме, но есть другое возможное решение:

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];

используя только 2 звонка на NSCalendar.

1 голос
/ 16 января 2010

Чтобы сделать то, что вы хотите, вы должны найти диапазон дней в месяце и месяцы в году для определенного календаря. Эта функция будет делать то, что вам нужно для любого календаря, который использует единицы день / месяц / год (или имеет некоторый эквивалентный сопоставленный):

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;
}

Если вы хотите указать этот год, вы можете назвать его просто как getDaysInYear([NSDate date]);, или вы можете создать дату из определенного года / других компонентов и передать ее. Вы также можете очень легко повторно реализовать его как вызов метода.

1 голос
/ 16 января 2010

Может быть, вы можете использовать селектор components:fromDate:toDate:options:, который предназначен (и я цитирую официальные документы Apple ): Возвращает, как объект NSDateComponents, используя указанные компоненты, разницу между двумя указанными датами . ?

Также прочитайте этот пост , который разъясняет поведение, которое вы видите.

0 голосов
/ 01 мая 2017

расширение Swift 3:

extension Date {
    public func isLeapYear() -> Bool {
        let components = Calendar.current.dateComponents([.year], from: self)

        guard let year = components.year else { return false }

        return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
    }
}
0 голосов
/ 01 января 2017

Другой пример в Swift 3:

let calendar = Calendar.current
let date = Date() // use any date in this year
if let yearInterval = calendar.dateInterval(of: Calendar.Component.year, for: date),
   let daysInYear = calendar.dateComponents([Calendar.Component.day], from: yearInterval.start, to: yearInterval.end).day
{
    print(daysInYear)
}

В Objective-C:

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate* date = [NSDate date];
NSDate* startOfYear = nil;
NSTimeInterval yearDuration = 0;
if ([calendar rangeOfUnit:NSCalendarUnitYear startDate:&startOfYear interval:&yearDuration forDate:d
]) {
    NSDateComponents *daysComponents = [calendar components:NSCalendarUnitDay fromDate:startOfYear toDate:[startOfYear dateByAddingTimeInterval:yearDuration] options:0];
    NSInteger daysInYear = daysComponents.day;
    NSLog(@"Days in year: %ld", daysInYear);
}
0 голосов
/ 03 марта 2016

Вау, это вовлеченные решения. Просто создайте дату 29 февраля текущего года и посмотрите, будет ли он преобразован в марш первым или нет.

-(BOOL)isLeapYear {
    NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
    components.month = 2;
    components.day = 29;

    NSDate *date = [[NSDate currentCalendar] dateFromComponents:components];
    return (date.month == 2 && date.day == 29);
}

** Обратите внимание, что некоторые из этих элементов, такие как date.month и date.day relay для других методов, не показаны, но вы поймете, что идея.

0 голосов
/ 05 ноября 2012

Вот ответ, предоставленный Уильямом Клеменсом, но в Задаче C:

                    int year;
                    int yearCode;

                    if ( year % 400 == 0 )
                        {yearCode = 366;} // Leap Year
                    else if ( year % 100 == 0 )
                    {
                        {yearCode = 365;} // Non Leap Year
                    }
                    else if ( year % 4 == 0 )
                    {
                         {yearCode = 366;} // Leap Year
                    }
                    else
                    {yearCode = 365;} // Non-Leap Year
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...