I am creating a calendar control of sorts...
One thing I need to know is how many weeks are there in a Month...
So NSCalendar
rangeOfUnit:inUnit:forDate
Seems to be exactly what I need...
Except I am noticing something that seems off and I can't quite figure out why this is happening...
The following code...
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]);
}
Is returning the following debug messages...
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
I cant quite figure out why I get 52 weeks in month 12.
Any clues?
Edit on 3/20/2010:
Seeing as how I couldnt use rangeOfUnit:inUnit:forDate
to calculate the number of weeks in a month. I decided to figure out a different way of calculating the same value.
I figured I should do this in a non-Gregorian localized way, so I attempted to start with getting the number of days in a week, but I got the result of 28 days in a week. So I started writing more code to figure out why...
I wanted to make sure that the type of NSCalendar that I was playing with was in fact what I was supposed to be getting... And that led me to finding some differences...
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);
And that got me the following log results...
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
Taking direction from @CarlNorum's experience, I compiled the code snippet as a 10.6 Cocoa application, and I got the following...
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
I saw hope in that creating a NSCalendar Instance explicitly as a Gregorian Calendar would lead to better results in my original problem... So I modified that original code
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]);
}
Unfortunately using a calendar created that way did not return a different result.
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
Compiling the code for Cocoa just for kicks, was actually amusing... As the results are really really different
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
I think this is when I give up...
Tried this code with the 10.6 SDK and it appears to work.
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
I tried it with the iPhone SDK and I get the same output you do. It is unclear that the iPhone SDK is outputting the correct values for many of the other months as well. I agree, for example, with the 10.6 SDK answer that Jan. has 6 weeks.
I do not see anything obviously wrong with your code.
I might first suggest heading to http://bugreport.apple.com and submitting a bug.
You can also head over to Apple's private developer forums ( http://developer.apple.com/devforums/ ) and try asking there.
Of course, you can also submit a tech support incident to Apple ( [email protected] - http://developer.apple.com/programs/adcbenefits/ ) ... if you don't have any in your ADC account, I believe Apple will happily sell you one and you can speak directly with an Apple engineer about this issue.
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