Objective-C:获取一个日历年的天数

时间:2013-02-18 16:38:17

标签: objective-c cocoa-touch cocoa nsdate nscalendar

我使用以下NSCalendar方法获取日历年中的天数:

NSRange range = [gregorian rangeOfUnit:NSDayCalendarUnit 
                                inUnit:NSYearCalendarUnit 
                               forDate:date];

我希望range.length类型为NSRange的返回值为365或366(天)。

但是,此代码会返回range.length 31,日期值为2005-06-06

我的代码出了什么问题?

这是完整的代码段:

NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];

[subArray enumerateObjectsUsingBlock:
   ^(NSDate *date, NSUInteger idx, BOOL *stop) {
   NSUInteger numberOfDays = [gregorian ordinalityOfUnit:NSDayCalendarUnit
   inUnit:NSYearCalendarUnit forDate:date];
}];

4 个答案:

答案 0 :(得分:2)

计算给定日期一年的天数:

NSDate *someDate = [NSDate date];

NSDate *beginningOfYear;
NSTimeInterval lengthOfYear;
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[gregorian rangeOfUnit:NSYearCalendarUnit
             startDate:&beginningOfYear
              interval:&lengthOfYear
               forDate:someDate];
NSDate *nextYear = [beginningOfYear dateByAddingTimeInterval:lengthOfYear];
NSInteger startDay = [gregorian ordinalityOfUnit:NSDayCalendarUnit
                                          inUnit:NSEraCalendarUnit
                                         forDate:beginningOfYear];
NSInteger endDay = [gregorian ordinalityOfUnit:NSDayCalendarUnit
                                        inUnit:NSEraCalendarUnit
                                       forDate:nextYear];
NSInteger daysInYear = endDay - startDay;

悲伤警告:这在1582年无效。

当格​​雷戈尔引入目前广泛使用的日历时,1582年需要修复太阳能与日历年。所以他们采取了务实的解决方案:他们刚于10月5日至14日放弃了。 (他们也不会疯狂地改变工作日)。因此,1582年只有355天。

附录:上面的代码只能在1582年后正常运行。例如,它返回到1500年的365天,即使今年是当时使用的朱利安日历中的闰年。格里高利历从1582年10月15日开始。在格里高利历上进行的计算在该日期之前没有定义。所以这样Apple的实现是正确的。我不知道1583年之前在Cocoa上的正确实施。

答案 1 :(得分:1)

如何查找给定年份的天数如下:虽然这不是问题的相对解决方案。

-(NSInteger)daysBetweenTwoDates:(NSDate *)fromDateTime andDate:(NSDate *)toDateTime{

    NSDate *fromDate;
    NSDate *toDate;

    NSCalendar *calendar = [NSCalendar currentCalendar];

    [calendar rangeOfUnit:NSDayCalendarUnit startDate:&fromDate interval:NULL forDate:fromDateTime];
    [calendar rangeOfUnit:NSDayCalendarUnit startDate:&toDate interval:NULL forDate:toDateTime];

    NSDateComponents *difference = [calendar components:NSDayCalendarUnit fromDate:fromDate toDate:toDate options:0];

    return [difference day]; 
}

-(void)someMethod {

    NSString *yourYear=@"2012";

    NSDate *date1 = [NSDate dateWithString:[NSString stringWithFormat:@"%@-01-01 00:00:00 +0000",yourYear]];
    NSDate *date2 = [NSDate dateWithString:[NSString stringWithFormat:@"%@-12-31 00:00:00 +0000",yourYear]];

    NSInteger numberOfDays=[self daysBetweenTwoDates:date1 andDate:date2];    

    NSLog(@"There are %ld days in between the two dates.", numberOfDays);
}            

编辑:

由于dateWithString:已弃用,您可以使用

NSDateFormatter *dateFormatter=[[NSDateFormatter alloc] init];
[dateFormatter dateFormat]=@"dd-MM-yyyy";
NSDate *date=[dateFormatter dateFromString:dateString];

以形成date1date2

答案 2 :(得分:1)

这是一个相对干净的版本。这是NSCalendar上的一个类别。

- (NSInteger) daysInYear:(NSInteger) year {
    NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
    dateComponents.year = year;
    dateComponents.month = dateComponents.day = 1;
    NSDate *firstOfYear = [self dateFromComponents:dateComponents];
    dateComponents.year = year + 1;
    NSDate *firstOfFollowingYear = [self dateFromComponents:dateComponents];

    return [[self components:NSDayCalendarUnit
                   fromDate:firstOfYear
                     toDate:firstOfFollowingYear
                     options:0] day];    
}

感谢AKV指出-components:fromDate:toDate:options在这种情况下会起作用。

这似乎不适用于1582或之前,根据Nikolai Ruhe的回答,因为公历日历计算在此之前没有定义。

答案 3 :(得分:0)

您将获得约会当月的天数。

您可以使用相同的功能,只需将月份作为月份传递。如果range.length返回28,那么一年中的总天数将是365,如果它返回29,那么天数将是366。