-2

Before giving downvote, comment the reason

I have created a UIDatePicker with minimum & maximum date values (i.e. 6 months of date picker) Now, i need to get 7 days from selected date. There i need to check the conditions,

  • If date is today date i need to get 7 days from today onwards
  • If date is last date (i.e. last date of picker) need to get last 7 days including last day
  • If date is middle of today's date & last date i need to get last 3 days, next 3 days including today date. And, also while getting last & next 3 days it shouldn't get exceed with picker's date limit.

Here's my code snippet:

- (void)addDays:(NSInteger)range {
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"dd-MM-yyyy"];
    
    NSDate *startDate = self.selectedDate;
    
    for (int x = 0; x <= range; x++) {
        NSLog(@"%@", [dateFormat stringFromDate:startDate]);
        startDate = [startDate dateByAddingTimeInterval:(60 * 60 * 24)];
    }
}
 
- (void)minusDays:(NSInteger)range {
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"dd-MM-yyyy"];
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *comps = [NSDateComponents new];
    
    for (NSInteger i=0; i<range; i++) {
        comps.day += -1;
        
        NSDate *date = [calendar dateByAddingComponents:comps toDate:self.selectedDate options:0];
        NSDateComponents *components = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:date];
        NSLog(@"%@", [dateFormat stringFromDate:[calendar dateFromComponents:components]]);
    }
}
 
- (void)calculateDateRange {
    
    if ([dateArray count] > 0) {
        [dateArray removeAllObjects];
    }
    
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *lastcomponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:[NSDate date]];
    lastcomponents.month += 6;
    
    NSDateFormatter *formatter = [NSDateFormatter new];
    [formatter setDateFormat:@"yyyy/MM/dd"];
    
    NSDate *currentDate = [NSDate date];
    NSDate *selectedD = self.selectedDate;
    NSDate *endDate = [calendar dateFromComponents:lastcomponents];
    
    NSDate *fromDate;
    NSDate *toDate;
    
    [calendar rangeOfUnit:NSDayCalendarUnit startDate:&fromDate interval:NULL forDate:currentDate];
    [calendar rangeOfUnit:NSDayCalendarUnit startDate:&toDate interval:NULL forDate:selectedD];
    NSDateComponents *difference = [calendar components:NSDayCalendarUnit fromDate:fromDate toDate:toDate options:0];
    NSInteger first = [difference day];
    
    [calendar rangeOfUnit:NSDayCalendarUnit startDate:&fromDate interval:NULL forDate:selectedD];
    [calendar rangeOfUnit:NSDayCalendarUnit startDate:&toDate interval:NULL forDate:endDate];
    NSDateComponents *difference2 = [calendar components:NSDayCalendarUnit fromDate:fromDate toDate:toDate options:0];
    NSInteger second = [difference2 day];
    
    if ((first == 0 || first < 3) && second > 7) {
        [self addDays:7];
    } else if (first >= 3 && second > 7) {
        [self minusDays:3];
        [self addDays:3];
    }else if (second == 7 || second < 7) {
        [self minusDays:7];
    }
}

This is working fine. But, can't get exact last & previous days.

Anyone has idea on this?

Community
  • 1
  • 1
Praveenkumar
  • 24,084
  • 23
  • 95
  • 173
  • 2
    No, you can't use 60*60*24 to be one day. Ever. Let me add an answer... – Fogmeister Nov 11 '14 at 11:15
  • Please explain what "If date is middle of today's date & last date i need to get last 3 days, next 3 days including today date. And, also while getting last & next 3 days it shouldn't get exceed with picker's date limit." This is VERY confusing and obviously doesn't mean what I think it means. – Fogmeister Nov 11 '14 at 12:02
  • It means, my date range is **11th Nov'14 to 11th May'15** So, if i select 16th Nov'14. I need get last 3 days from selected date (i.e. 16th Nov'14) to next 3 days from selected date (13, 14, 15, 16, 17 & 19th Nov'14) dates i need to retrieve it. – Praveenkumar Nov 11 '14 at 12:09
  • Please take a look at my edit. You have still not provided anything that makes me think I need to change my code. – Fogmeister Nov 11 '14 at 12:14
  • OK, you edited your comment. Still my code does exactly what you want. Please let me know which bit of my code you think will not work. I will explain it to you. – Fogmeister Nov 11 '14 at 12:15
  • Also, explain **WHY** you think my code doesn't work. What about it **EXACTLY** is wrong. Saying "Nope it doesn't." is about as useful as telling me your favourite colour. – Fogmeister Nov 11 '14 at 12:20
  • Yeah, you got my point. As you explained clearly there. So, let consider the Min date - 11/11/2014 & Maximum date - 11/06/2015 (dd/MM/yyyy) Now, am choosing a date - 16/11/2014. It should print 7 days and shouldn't exceed than date picker's range. Finally, it's not giving output as date range from 13/11/2014 - 19/11/2014) – Praveenkumar Nov 11 '14 at 12:21
  • What do you mean "printing date range" where in any of your question our comments did you ever mention anything about printing anything? – Fogmeister Nov 11 '14 at 12:23
  • That is final output i am getting it. – Praveenkumar Nov 11 '14 at 12:26
  • Do you mean you want each date to appear in the console? With NSLog? – Fogmeister Nov 11 '14 at 12:28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/64708/discussion-between-praveen-and-fogmeister). – Praveenkumar Nov 11 '14 at 12:29

1 Answers1

2

My interpretation of your needs

You have a date picker. When a date is picked you need to create a 7 day range around that selected date.

So, if the selected date is 15/11/2014 then you want 3 days either side so...

12/11/2014 - 18/11/2014.

However, the date range cannot exceed the limits of the date picker. So if the minimum date on the date picker is set to 14/11/2014 then (in the above example) the date range would be...

14/11/2014 - 21/11/2014

Even after your additional explanation this is still my interpretation. And my code does exactly this.

Solution

You CANNOT use 60*60*24 to mean one day. This is just wrong. When dealing with dates you should always be using NSDateComponents and NSCalendar.

Also, break down your problem into small steps. There is no reason to do everything in one giant function.

OK I guess you have a datePicker action somewhere so I'd code it like this...

- (void)datePickerDateChanged
{
    NSDate *minimumDate = self.datePicker.minimumDate;
    NSDate *maximumDate = self.datePicker.maximumDate;

    NSDate *selectedDate = self.datePicker.date;

    NSDate *startDate;
    NSDate *endDate;

    if ([self numberOfDaysFromDate:minimumDate toDate:selectedDate] < 3) {
        // get 7 days after minimumDate
        startDate = minimumDate;
        endDate = [self dateByAddingDays:6 toDate:minimumDate];
    } else if ([self numberOfDaysFromDate:selectedDate toDate:maximumDate] < 3) {
        // get 7 days before maximumDate
        startDate = [self dateByAddingDays:-6 toDate:maximumDate];
        endDate = maximumDate;
    } else {
        // get 3 days before and 3 days after selectedDate
        startDate = [self dateByAddingDays:-3 toDate:selectedDate];
        endDate = [self dateByAddingDays:3 toDate:selectedDate];
    }
    // Here startDate and endDate define your date range.

}

- (NSDate *)dateByAddingDays:(NSInteger)days toDate:(NSDate *)date
{
    NSCalendar *calendar = [NSCalendar currentCalendar];

    NSDateComponents *components = [NSDateComponents new];
    components.day = days;

    return [calendar dateByAddingComponents:components toDate:date options:0];
}

- (NSInteger)numberOfDaysFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate
{
    NSCalendar *calendar = [NSCalendar currentCalendar];

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

    // always return positive. We just want magnitude of days.
    return components.day > 0 ? components.day : -components.day;
}

This is untested and just a first attempt.

Praveenkumar
  • 24,084
  • 23
  • 95
  • 173
Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • Thanks for your time. Its working fine. But, how to execute for this, *If date is middle of today's date & last date i need to get last 3 days, next 3 days including today date. And, also while getting last & next 3 days it shouldn't get exceed with picker's date limit.* – Praveenkumar Nov 11 '14 at 11:49
  • @Praveen take a look at my code. It does all of that. – Fogmeister Nov 11 '14 at 11:49
  • Nope it doesn't. My constraint is if the selected date is middle of min & max dates. It should get last 3 days from current date, next 3 days including current date. Your code is not executing like this. – Praveenkumar Nov 11 '14 at 11:55
  • @Praveen Please provide a precise example. i.e. minimum date, maximum date, selected date and what the start date and end date should be. Everything you have said is included in my code. If you're not explaining it properly then I can't code for it. – Fogmeister Nov 11 '14 at 11:57