NSCalendar:一个月内出现问题

时间:2010-03-14 17:31:45

标签: iphone objective-c cocoa nscalendar

我正在创建各种日历控件...

我需要知道的一件事是一个月内有多少个星期......

所以NSCalendar rangeOfUnit:inUnit:forDate似乎正是我需要的......

除非我注意到一些似乎有些东西,我无法弄清楚为什么会这样......

以下代码......

NSCalendar *calendar = [NSCalendar currentCalendar];

NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
[dateComponents setYear: 2010];
[dateComponents setDay: 1];

for (int x=1; x<=12; x++)
{
    [dateComponents setMonth: x];

    NSDate *date = [calendar dateFromComponents:dateComponents];
    NSLog(@"Date: %@", date);

    NSRange range = [calendar rangeOfUnit: NSWeekCalendarUnit
                                   inUnit: NSMonthCalendarUnit
                                  forDate:date];

    NSLog(@"%d Weeks in Month %d", range.length, [dateComponents month]);

}

返回以下调试消息......

2010-03-14 13:08:10.350 Scrap[4256:207] Date: 2010-01-01 00:00:00 -0500
2010-03-14 13:08:10.351 Scrap[4256:207] 5 Weeks in Month 1
2010-03-14 13:08:10.352 Scrap[4256:207] Date: 2010-02-01 00:00:00 -0500
2010-03-14 13:08:10.352 Scrap[4256:207] 4 Weeks in Month 2
2010-03-14 13:08:10.353 Scrap[4256:207] Date: 2010-03-01 00:00:00 -0500
2010-03-14 13:08:10.353 Scrap[4256:207] 5 Weeks in Month 3
2010-03-14 13:08:10.354 Scrap[4256:207] Date: 2010-04-01 00:00:00 -0400
2010-03-14 13:08:10.355 Scrap[4256:207] 5 Weeks in Month 4
2010-03-14 13:08:10.356 Scrap[4256:207] Date: 2010-05-01 00:00:00 -0400
2010-03-14 13:08:10.357 Scrap[4256:207] 5 Weeks in Month 5
2010-03-14 13:08:10.358 Scrap[4256:207] Date: 2010-06-01 00:00:00 -0400
2010-03-14 13:08:10.358 Scrap[4256:207] 5 Weeks in Month 6
2010-03-14 13:08:10.359 Scrap[4256:207] Date: 2010-07-01 00:00:00 -0400
2010-03-14 13:08:10.360 Scrap[4256:207] 5 Weeks in Month 7
2010-03-14 13:08:10.361 Scrap[4256:207] Date: 2010-08-01 00:00:00 -0400
2010-03-14 13:08:10.364 Scrap[4256:207] 5 Weeks in Month 8
2010-03-14 13:08:10.364 Scrap[4256:207] Date: 2010-09-01 00:00:00 -0400
2010-03-14 13:08:10.365 Scrap[4256:207] 5 Weeks in Month 9
2010-03-14 13:08:10.366 Scrap[4256:207] Date: 2010-10-01 00:00:00 -0400
2010-03-14 13:08:10.366 Scrap[4256:207] 5 Weeks in Month 10
2010-03-14 13:08:10.367 Scrap[4256:207] Date: 2010-11-01 00:00:00 -0400
2010-03-14 13:08:10.367 Scrap[4256:207] 5 Weeks in Month 11
2010-03-14 13:08:10.369 Scrap[4256:207] Date: 2010-12-01 00:00:00 -0500
2010-03-14 13:08:10.369 Scrap[4256:207] 52 Weeks in Month 12

我无法弄清楚为什么我会在12月份获得52周。

任何线索?

2010年3月20日编辑:

看我如何使用rangeOfUnit:inUnit:forDate来计算一个月内的周数。我决定找出一种计算相同值的不同方法。

我认为我应该以非格里高利的本地化方式进行此操作,因此我尝试从一周内获得一天的天数开始,但我得到了一周内28天的结果。所以我开始编写更多代码来弄清楚为什么......

我想确保我正在玩的NSCalendar的类型实际上是我应该得到的......这导致我发现了一些差异......

NSCalendar *currentCalendar = [NSCalendar currentCalendar];

NSLog(@"Calendar with 'currentCalendar' Identifier: %@", 
      [currentCalendar calendarIdentifier]);

NSCalendar *calendarWithIdentifier = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar] autorelease];

NSLog(@"Calendar created with identifier Identifier: %@", 
      [calendarWithIdentifier calendarIdentifier]);

NSDate *now = [[NSDate alloc] init];

NSDateComponents *currentMonth = [currentCalendar components: NSMonthCalendarUnit | NSYearCalendarUnit
                                                    fromDate: now];

NSDate *currentMonthDate = [currentCalendar dateFromComponents: currentMonth];

NSRange daysInWeekRange = [currentCalendar rangeOfUnit: NSDayCalendarUnit
                                                inUnit: NSWeekCalendarUnit
                                               forDate: currentMonthDate];

NSLog(@"CurrentCalendar: Length:%u Location:%u", daysInWeekRange.length, daysInWeekRange.location);

currentMonth = [calendarWithIdentifier components: NSMonthCalendarUnit | NSYearCalendarUnit 
                                         fromDate: now];

currentMonthDate = [calendarWithIdentifier dateFromComponents: currentMonth];

daysInWeekRange = [calendarWithIdentifier rangeOfUnit: NSDayCalendarUnit
                                               inUnit: NSWeekCalendarUnit
                                              forDate: currentMonthDate];

NSLog(@"GregorianCalendar: Length:%u Location:%u", daysInWeekRange.length, daysInWeekRange.location);

这让我得到以下日志结果......

2010-03-20 21:02:27.245 Scrap[52189:207] Calendar with 'currentCalendar' Identifier: gregorian
2010-03-20 21:02:27.246 Scrap[52189:207] Calendar created with identifier Identifier: gregorian
2010-03-20 21:02:27.248 Scrap[52189:207] CurrentCalendar: Length:28 Location:1
2010-03-20 21:02:27.249 Scrap[52189:207] GregorianCalendar: Length:7 Location:1

从@ CarlNorum的经验中获得指导,我将代码片段编译为10.6 Cocoa应用程序,我得到了以下内容......

2010-03-20 21:05:35.636 ScrapCocoa[52238:a0f] Calendar with 'currentCalendar' Identifier: gregorian
2010-03-20 21:05:35.636 ScrapCocoa[52238:a0f] Calendar created with identifier Identifier: gregorian
2010-03-20 21:05:35.637 ScrapCocoa[52238:a0f] CurrentCalendar: Length:6 Location:1
2010-03-20 21:05:35.638 ScrapCocoa[52238:a0f] GregorianCalendar: Length:7 Location:1

我看到希望明确创建一个NSCalendar实例作为格里高利日历会在我原来的问题中产生更好的结果......所以我修改了原始代码

NSCalendar *currentCalendar = [NSCalendar currentCalendar];

NSLog(@"Calendar with 'currentCalendar' Identifier: %@", 
      [currentCalendar calendarIdentifier]);

NSCalendar *calendarWithIdentifier = [[[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar] autorelease];

NSLog(@"Calendar created with identifier Identifier: %@", 
      [calendarWithIdentifier calendarIdentifier]);

NSDateComponents *dateComponents = [[[NSDateComponents alloc] init] autorelease];
[dateComponents setYear: 2010];
[dateComponents setDay: 1];

for (int x=1; x<=12; x++)
{
    [dateComponents setMonth: x];

    NSDate *date = [currentCalendar dateFromComponents: dateComponents];
    NSRange range = [currentCalendar rangeOfUnit: NSWeekCalendarUnit
                                          inUnit: NSMonthCalendarUnit
                                         forDate: date];

    NSLog(@"CurrentCalendar Date: %@", date);
    NSLog(@"CurrentCalendar: %d Weeks in Month %d", range.length, [dateComponents month]);

    date = [calendarWithIdentifier dateFromComponents: dateComponents];

    range = [calendarWithIdentifier rangeOfUnit: NSWeekCalendarUnit
                                         inUnit: NSMonthCalendarUnit
                                        forDate: date];

    NSLog(@"GregorianCalendar Date: %@", date);
    NSLog(@"GregorianCalendar: %d Weeks in Month %d", range.length, [dateComponents month]);

}

不幸的是,使用以这种方式创建的日历并没有返回不同的结果。

2010-03-20 21:15:40.465 Scrap[52367:207] Calendar with 'currentCalendar' Identifier: gregorian
2010-03-20 21:15:40.466 Scrap[52367:207] Calendar created with identifier Identifier: gregorian
2010-03-20 21:15:40.468 Scrap[52367:207] CurrentCalendar Date: 2010-01-01 00:00:00 -0500
2010-03-20 21:15:40.468 Scrap[52367:207] CurrentCalendar: 5 Weeks in Month 1
2010-03-20 21:15:40.469 Scrap[52367:207] GregorianCalendar Date: 2010-01-01 00:00:00 -0500
2010-03-20 21:15:40.470 Scrap[52367:207] GregorianCalendar: 5 Weeks in Month 1
2010-03-20 21:15:40.471 Scrap[52367:207] CurrentCalendar Date: 2010-02-01 00:00:00 -0500
2010-03-20 21:15:40.471 Scrap[52367:207] CurrentCalendar: 4 Weeks in Month 2
2010-03-20 21:15:40.472 Scrap[52367:207] GregorianCalendar Date: 2010-02-01 00:00:00 -0500
2010-03-20 21:15:40.473 Scrap[52367:207] GregorianCalendar: 4 Weeks in Month 2
2010-03-20 21:15:40.473 Scrap[52367:207] CurrentCalendar Date: 2010-03-01 00:00:00 -0500
2010-03-20 21:15:40.474 Scrap[52367:207] CurrentCalendar: 5 Weeks in Month 3
2010-03-20 21:15:40.475 Scrap[52367:207] GregorianCalendar Date: 2010-03-01 00:00:00 -0500
2010-03-20 21:15:40.475 Scrap[52367:207] GregorianCalendar: 5 Weeks in Month 3
2010-03-20 21:15:40.476 Scrap[52367:207] CurrentCalendar Date: 2010-04-01 00:00:00 -0400
2010-03-20 21:15:40.477 Scrap[52367:207] CurrentCalendar: 5 Weeks in Month 4
2010-03-20 21:15:40.478 Scrap[52367:207] GregorianCalendar Date: 2010-04-01 00:00:00 -0400
2010-03-20 21:15:40.479 Scrap[52367:207] GregorianCalendar: 5 Weeks in Month 4
2010-03-20 21:15:40.480 Scrap[52367:207] CurrentCalendar Date: 2010-05-01 00:00:00 -0400
2010-03-20 21:15:40.480 Scrap[52367:207] CurrentCalendar: 5 Weeks in Month 5
2010-03-20 21:15:40.482 Scrap[52367:207] GregorianCalendar Date: 2010-05-01 00:00:00 -0400
2010-03-20 21:15:40.482 Scrap[52367:207] GregorianCalendar: 5 Weeks in Month 5
2010-03-20 21:15:40.483 Scrap[52367:207] CurrentCalendar Date: 2010-06-01 00:00:00 -0400
2010-03-20 21:15:40.483 Scrap[52367:207] CurrentCalendar: 5 Weeks in Month 6
2010-03-20 21:15:40.484 Scrap[52367:207] GregorianCalendar Date: 2010-06-01 00:00:00 -0400
2010-03-20 21:15:40.485 Scrap[52367:207] GregorianCalendar: 5 Weeks in Month 6
2010-03-20 21:15:40.485 Scrap[52367:207] CurrentCalendar Date: 2010-07-01 00:00:00 -0400
2010-03-20 21:15:40.486 Scrap[52367:207] CurrentCalendar: 5 Weeks in Month 7
2010-03-20 21:15:40.486 Scrap[52367:207] GregorianCalendar Date: 2010-07-01 00:00:00 -0400
2010-03-20 21:15:40.487 Scrap[52367:207] GregorianCalendar: 5 Weeks in Month 7
2010-03-20 21:15:40.488 Scrap[52367:207] CurrentCalendar Date: 2010-08-01 00:00:00 -0400
2010-03-20 21:15:40.488 Scrap[52367:207] CurrentCalendar: 5 Weeks in Month 8
2010-03-20 21:15:40.489 Scrap[52367:207] GregorianCalendar Date: 2010-08-01 00:00:00 -0400
2010-03-20 21:15:40.489 Scrap[52367:207] GregorianCalendar: 5 Weeks in Month 8
2010-03-20 21:15:40.490 Scrap[52367:207] CurrentCalendar Date: 2010-09-01 00:00:00 -0400
2010-03-20 21:15:40.491 Scrap[52367:207] CurrentCalendar: 5 Weeks in Month 9
2010-03-20 21:15:40.491 Scrap[52367:207] GregorianCalendar Date: 2010-09-01 00:00:00 -0400
2010-03-20 21:15:40.492 Scrap[52367:207] GregorianCalendar: 5 Weeks in Month 9
2010-03-20 21:15:40.493 Scrap[52367:207] CurrentCalendar Date: 2010-10-01 00:00:00 -0400
2010-03-20 21:15:40.493 Scrap[52367:207] CurrentCalendar: 5 Weeks in Month 10
2010-03-20 21:15:40.494 Scrap[52367:207] GregorianCalendar Date: 2010-10-01 00:00:00 -0400
2010-03-20 21:15:40.494 Scrap[52367:207] GregorianCalendar: 5 Weeks in Month 10
2010-03-20 21:15:40.495 Scrap[52367:207] CurrentCalendar Date: 2010-11-01 00:00:00 -0400
2010-03-20 21:15:40.496 Scrap[52367:207] CurrentCalendar: 5 Weeks in Month 11
2010-03-20 21:15:40.496 Scrap[52367:207] GregorianCalendar Date: 2010-11-01 00:00:00 -0400
2010-03-20 21:15:40.497 Scrap[52367:207] GregorianCalendar: 5 Weeks in Month 11
2010-03-20 21:15:40.498 Scrap[52367:207] CurrentCalendar Date: 2010-12-01 00:00:00 -0500
2010-03-20 21:15:40.498 Scrap[52367:207] CurrentCalendar: 52 Weeks in Month 12
2010-03-20 21:15:40.499 Scrap[52367:207] GregorianCalendar Date: 2010-12-01 00:00:00 -0500
2010-03-20 21:15:40.500 Scrap[52367:207] GregorianCalendar: 52 Weeks in Month 12

仅为踢球编译Cocoa的代码,实际上很有趣...... 由于结果真的不同

2010-03-20 21:11:24.610 ScrapCocoa[52313:a0f] Calendar with 'currentCalendar' Identifier: gregorian
2010-03-20 21:11:24.611 ScrapCocoa[52313:a0f] Calendar created with identifier Identifier: gregorian
2010-03-20 21:11:24.613 ScrapCocoa[52313:a0f] CurrentCalendar Date: 2010-01-01 00:00:00 -0500
2010-03-20 21:11:24.613 ScrapCocoa[52313:a0f] CurrentCalendar: 6 Weeks in Month 1
2010-03-20 21:11:24.614 ScrapCocoa[52313:a0f] GregorianCalendar Date: 2010-01-01 00:00:00 -0500
2010-03-20 21:11:24.615 ScrapCocoa[52313:a0f] GregorianCalendar: 5 Weeks in Month 1
2010-03-20 21:11:24.616 ScrapCocoa[52313:a0f] CurrentCalendar Date: 2010-02-01 00:00:00 -0500
2010-03-20 21:11:24.616 ScrapCocoa[52313:a0f] CurrentCalendar: 5 Weeks in Month 2
2010-03-20 21:11:24.617 ScrapCocoa[52313:a0f] GregorianCalendar Date: 2010-02-01 00:00:00 -0500
2010-03-20 21:11:24.618 ScrapCocoa[52313:a0f] GregorianCalendar: 4 Weeks in Month 2
2010-03-20 21:11:24.619 ScrapCocoa[52313:a0f] CurrentCalendar Date: 2010-03-01 00:00:00 -0500
2010-03-20 21:11:24.619 ScrapCocoa[52313:a0f] CurrentCalendar: 5 Weeks in Month 3
2010-03-20 21:11:24.620 ScrapCocoa[52313:a0f] GregorianCalendar Date: 2010-03-01 00:00:00 -0500
2010-03-20 21:11:24.621 ScrapCocoa[52313:a0f] GregorianCalendar: 5 Weeks in Month 3
2010-03-20 21:11:24.622 ScrapCocoa[52313:a0f] CurrentCalendar Date: 2010-04-01 00:00:00 -0400
2010-03-20 21:11:24.622 ScrapCocoa[52313:a0f] CurrentCalendar: 5 Weeks in Month 4
2010-03-20 21:11:24.623 ScrapCocoa[52313:a0f] GregorianCalendar Date: 2010-04-01 00:00:00 -0400
2010-03-20 21:11:24.623 ScrapCocoa[52313:a0f] GregorianCalendar: 5 Weeks in Month 4
2010-03-20 21:11:24.624 ScrapCocoa[52313:a0f] CurrentCalendar Date: 2010-05-01 00:00:00 -0400
2010-03-20 21:11:24.625 ScrapCocoa[52313:a0f] CurrentCalendar: 6 Weeks in Month 5
2010-03-20 21:11:24.625 ScrapCocoa[52313:a0f] GregorianCalendar Date: 2010-05-01 00:00:00 -0400
2010-03-20 21:11:24.626 ScrapCocoa[52313:a0f] GregorianCalendar: 6 Weeks in Month 5
2010-03-20 21:11:24.627 ScrapCocoa[52313:a0f] CurrentCalendar Date: 2010-06-01 00:00:00 -0400
2010-03-20 21:11:24.627 ScrapCocoa[52313:a0f] CurrentCalendar: 5 Weeks in Month 6
2010-03-20 21:11:24.628 ScrapCocoa[52313:a0f] GregorianCalendar Date: 2010-06-01 00:00:00 -0400
2010-03-20 21:11:24.628 ScrapCocoa[52313:a0f] GregorianCalendar: 5 Weeks in Month 6
2010-03-20 21:11:24.629 ScrapCocoa[52313:a0f] CurrentCalendar Date: 2010-07-01 00:00:00 -0400
2010-03-20 21:11:24.630 ScrapCocoa[52313:a0f] CurrentCalendar: 5 Weeks in Month 7
2010-03-20 21:11:24.630 ScrapCocoa[52313:a0f] GregorianCalendar Date: 2010-07-01 00:00:00 -0400
2010-03-20 21:11:24.631 ScrapCocoa[52313:a0f] GregorianCalendar: 5 Weeks in Month 7
2010-03-20 21:11:24.632 ScrapCocoa[52313:a0f] CurrentCalendar Date: 2010-08-01 00:00:00 -0400
2010-03-20 21:11:24.632 ScrapCocoa[52313:a0f] CurrentCalendar: 5 Weeks in Month 8
2010-03-20 21:11:24.633 ScrapCocoa[52313:a0f] GregorianCalendar Date: 2010-08-01 00:00:00 -0400
2010-03-20 21:11:24.633 ScrapCocoa[52313:a0f] GregorianCalendar: 6 Weeks in Month 8
2010-03-20 21:11:24.634 ScrapCocoa[52313:a0f] CurrentCalendar Date: 2010-09-01 00:00:00 -0400
2010-03-20 21:11:24.635 ScrapCocoa[52313:a0f] CurrentCalendar: 5 Weeks in Month 9
2010-03-20 21:11:24.636 ScrapCocoa[52313:a0f] GregorianCalendar Date: 2010-09-01 00:00:00 -0400
2010-03-20 21:11:24.636 ScrapCocoa[52313:a0f] GregorianCalendar: 5 Weeks in Month 9
2010-03-20 21:11:24.637 ScrapCocoa[52313:a0f] CurrentCalendar Date: 2010-10-01 00:00:00 -0400
2010-03-20 21:11:24.637 ScrapCocoa[52313:a0f] CurrentCalendar: 6 Weeks in Month 10
2010-03-20 21:11:24.638 ScrapCocoa[52313:a0f] GregorianCalendar Date: 2010-10-01 00:00:00 -0400
2010-03-20 21:11:24.639 ScrapCocoa[52313:a0f] GregorianCalendar: 5 Weeks in Month 10
2010-03-20 21:11:24.640 ScrapCocoa[52313:a0f] CurrentCalendar Date: 2010-11-01 00:00:00 -0400
2010-03-20 21:11:24.640 ScrapCocoa[52313:a0f] CurrentCalendar: 5 Weeks in Month 11
2010-03-20 21:11:24.641 ScrapCocoa[52313:a0f] GregorianCalendar Date: 2010-11-01 00:00:00 -0400
2010-03-20 21:11:24.641 ScrapCocoa[52313:a0f] GregorianCalendar: 5 Weeks in Month 11
2010-03-20 21:11:24.642 ScrapCocoa[52313:a0f] CurrentCalendar Date: 2010-12-01 00:00:00 -0500
2010-03-20 21:11:24.642 ScrapCocoa[52313:a0f] CurrentCalendar: 5 Weeks in Month 12
2010-03-20 21:11:24.643 ScrapCocoa[52313:a0f] GregorianCalendar Date: 2010-12-01 00:00:00 -0500
2010-03-20 21:11:24.644 ScrapCocoa[52313:a0f] GregorianCalendar: 5 Weeks in Month 12

我认为这是我放弃的时候......

1 个答案:

答案 0 :(得分:2)

使用10.6 SDK尝试使用此代码,它似乎可以正常工作。

2010-03-14 19:11:49.424 Untitled[61397:a0f] Date: 2010-01-01 00:00:00 -0500
2010-03-14 19:11:49.425 Untitled[61397:a0f] 6 Weeks in Month 1
2010-03-14 19:11:49.426 Untitled[61397:a0f] Date: 2010-02-01 00:00:00 -0500
2010-03-14 19:11:49.427 Untitled[61397:a0f] 5 Weeks in Month 2
2010-03-14 19:11:49.428 Untitled[61397:a0f] Date: 2010-03-01 00:00:00 -0500
2010-03-14 19:11:49.429 Untitled[61397:a0f] 5 Weeks in Month 3
2010-03-14 19:11:49.429 Untitled[61397:a0f] Date: 2010-04-01 00:00:00 -0400
2010-03-14 19:11:49.430 Untitled[61397:a0f] 5 Weeks in Month 4
2010-03-14 19:11:49.431 Untitled[61397:a0f] Date: 2010-05-01 00:00:00 -0400
2010-03-14 19:11:49.431 Untitled[61397:a0f] 6 Weeks in Month 5
2010-03-14 19:11:49.432 Untitled[61397:a0f] Date: 2010-06-01 00:00:00 -0400
2010-03-14 19:11:49.433 Untitled[61397:a0f] 5 Weeks in Month 6
2010-03-14 19:11:49.434 Untitled[61397:a0f] Date: 2010-07-01 00:00:00 -0400
2010-03-14 19:11:49.434 Untitled[61397:a0f] 5 Weeks in Month 7
2010-03-14 19:11:49.435 Untitled[61397:a0f] Date: 2010-08-01 00:00:00 -0400
2010-03-14 19:11:49.436 Untitled[61397:a0f] 5 Weeks in Month 8
2010-03-14 19:11:49.437 Untitled[61397:a0f] Date: 2010-09-01 00:00:00 -0400
2010-03-14 19:11:49.437 Untitled[61397:a0f] 5 Weeks in Month 9
2010-03-14 19:11:49.438 Untitled[61397:a0f] Date: 2010-10-01 00:00:00 -0400
2010-03-14 19:11:49.439 Untitled[61397:a0f] 6 Weeks in Month 10
2010-03-14 19:11:49.439 Untitled[61397:a0f] Date: 2010-11-01 00:00:00 -0400
2010-03-14 19:11:49.440 Untitled[61397:a0f] 5 Weeks in Month 11
2010-03-14 19:11:49.441 Untitled[61397:a0f] Date: 2010-12-01 00:00:00 -0500
2010-03-14 19:11:49.441 Untitled[61397:a0f] 5 Weeks in Month 12

我尝试使用iPhone SDK,我得到了相同的输出。目前还不清楚iPhone SDK是否也为其他许多月输出了正确的值。例如,我同意1月份有6周的10.6 SDK答案。

我的代码没有看到任何明显错误。

我可能会先建议前往http://bugreport.apple.com并提交错误。

您也可以访问Apple的私人开发者论坛(http://developer.apple.com/devforums/)并尝试询问。

当然,您也可以向Apple提交技术支持事件(dts@apple.com - http://developer.apple.com/programs/adcbenefits/)...如果您的ADC帐户中没有任何内容,我相信Apple会乐意出售你是一个,你可以直接与Apple工程师谈论这个问题。