8

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

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

我期待一个类型为 365 或 366(天)的range.length返回值。NSRange

但是,此代码range.length31日期值返回 a 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

4 回答 4

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 年,即 Gregor 引入目前广泛使用的日历的那一年,需要修复以使太阳与日历年保持一致。所以他们采用了务实的解决方案:他们刚刚在 10 月 5 日至 14 日放弃了。(他们也没有疯狂到改变工作日)。因此,1582 年只有 355 天。

附录:上面的代码只在 1582 年之后才能正常工作。例如,它返回 1500 年的 365 天,即使今年在当时使用的儒略历中是闰年。公历从 1582 年 10 月 15 日开始。在公历上进行的计算只是在该日期之前没有定义。所以这样苹果的实现是正确的。在 1583 年之前,我不知道 Cocoa 上的正确实现。

于 2013-02-18T18:00:01.417 回答
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

于 2013-02-18T17:32:13.633 回答
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 的回答,这是因为在此之前根本没有定义公历计算。

于 2013-02-18T17:57:05.003 回答
0

您将获得日期当月的天数。

您可以使用相同的函数,只需传入一个以二月为月份的日期。如果 range.length 返回 28,则一年中的总天数将为 365,如果返回 29,则天数将为 366。

于 2013-02-18T16:44:43.537 回答