-1

I am using NSDateComponents and NSCalendar to get the dates between two dates.

// Get dates between before and after
NSDateComponents *betweenDateComponents = [calendar components:componentFlags
                                                        fromDate:afterDate
                                                          toDate:beforeDate
                                                         options:0];

I then have a simple for loop that is based on the components' day property:

  for (int i = 1; i < betweenDateComponents.day; ++i) {

This works perfectly when I am working with all of the days for a week, or a month. If I filter by week, the day property logs as 6. If I filter by month the day property is 29, but for some reason when I filter by year, the day property logs as 29 instead of 364.

Why is the day property always wrong when I'm trying to work with a year?

Here is all of my code up until the for loop I included above:

// Set the date components according to the type of filter we're doing
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [NSDateComponents new];
    if (filterType == CommentFilterTypeWeeklyByDay) {
        [components setDay:-6];
    } else if (filterType == CommentFilterTypeMonthlyByDay) {
        [components setDay:-29];
    } else if (filterType == CommentFilterTypeYearlyByMonth) {
        [components setDay:-364];
    }

    NSUInteger componentFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;

    // Zero out before and after dates
    NSDate *beforeDate = [NSDate date];
    NSDateComponents *zeroComponents = [[NSCalendar currentCalendar] components:componentFlags fromDate:beforeDate];
    beforeDate = [calendar dateFromComponents:zeroComponents];

    NSDate *afterDate = [calendar dateByAddingComponents:components toDate:beforeDate options:0];
    zeroComponents = [[NSCalendar currentCalendar] components:componentFlags fromDate:afterDate];
    afterDate = [calendar dateFromComponents:zeroComponents];

    NSMutableArray *dates = [NSMutableArray new];
    [dates addObject:afterDate];

    // Get dates between before and after
    NSDateComponents *betweenDateComponents = [calendar components:componentFlags
                                                          fromDate:afterDate
                                                            toDate:beforeDate
                                                           options:0];
    NSLog(@"%d", betweenDateComponents.day);

    for (int i = 1; i < betweenDateComponents.day; ++i) {
user3344977
  • 3,584
  • 4
  • 32
  • 88
  • Because your components include `NSYearCalendarUnit` and `NSMonthCalendarUnit`, I suspect you'll have to use `month` and `year` instead of just `day`. The components are cumulative, not independent. – Ian MacDonald Oct 28 '14 at 17:33
  • This worked. I changed componentFlags to only include NSYearCalendarUnit and NSDayCalendarUnit. The day property is now logging correctly. Strange that this only affects month and year, but not the week. – user3344977 Oct 28 '14 at 17:38

1 Answers1

1

Because your components include NSYearCalendarUnit and NSMonthCalendarUnit, I suspect you'll have to use month and year instead of just day. The components are cumulative, not independent.

You will always be able to get just the number of days (regardless of how many months or years are between your dates) by changing your components:

NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [NSDateComponents new];

switch (filterType) {
  case CommentFilterTypeWeeklyByDay: [components setDay:-6]; break;
  case CommentFilterTypeMonthlyByDay: [components setDay:-29]; break;
  case CommentFilterTypeYearlyByMonth: [components setDay:-364]; break;
  case CommentFilterTypeCustom: [components setDay:-590]; break;
  default: break;
}

NSUInteger componentFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDate *beforeDate = [NSDate date];
NSDateComponents *zeroComponents = [[NSCalendar currentCalendar] components:componentFlags fromDate:beforeDate];
beforeDate = [calendar dateFromComponents:zeroComponents];

NSDate *afterDate = [calendar dateByAddingComponents:components toDate:beforeDate options:0];
zeroComponents = [[NSCalendar currentCalendar] components:componentFlags fromDate:afterDate];
afterDate = [calendar dateFromComponents:zeroComponents];

NSDateComponents *betweenDateComponents = [calendar components:NSDayCalendarUnit
                                                      fromDate:afterDate
                                                        toDate:beforeDate
                                                       options:0];

NSLog(@"%d", betweenDateComponents.day);

The NSLog here prints

6 for CommentFilterTypeWeeklyByDay

29 for CommentFilterTypeMonthlyByDay

364 for CommentFilterTypeYearlyByMonth

590 for CommentFilterTypeCustom

Ian MacDonald
  • 13,472
  • 2
  • 30
  • 51
  • The above doesn't work, unless I'm misunderstanding. With the above, should I be able to log betweenDateComponents.day as 364? – user3344977 Oct 28 '14 at 17:51
  • At this point, I'm basically setting NSYearCalendarUnit and NSDayCalendarUnit to get day to log as 364, or NSMonthCalendarUnit and NSDayCalendarUnit to get day to log as 29. – user3344977 Oct 28 '14 at 17:53
  • I'm not sure I follow what you're asking. If I modify your code to simply replace `components:componentFlags` with `components:NSDayCalendarUnit` in just the `betweenDateComponents` calculation, it returns `6`, `29`, and `364` for me when I select your different filters. – Ian MacDonald Oct 28 '14 at 17:55
  • If I do the above, the day property logs as -2. It either needs to be 6, 29, or 364. – user3344977 Oct 28 '14 at 17:58
  • I updated my answer to show you the exact code that I have run successfully. It is basically a copy of your code, but with the final `components:componentFlags` replaced with `components:NSDayCalendarUnit`. I have included the output of the `NSLog` lines to demonstrate its correctness. – Ian MacDonald Oct 28 '14 at 18:03
  • I figured out what I was doing wrong. I had changed componentFlags to only include NSDayCalendarUnit, when it should have been left alone. – user3344977 Oct 28 '14 at 18:40