0

Scenario:

I have an expense tracking iOS Application and I am storing expenses from a expense detail view controller into a table view (with fetched results controller) that shows the list of expenses along with the category and amount and date. I do have a date attribute in my entity "Money" which is a parent entity for either an expense or an income.

Question:

What I want is to basically categorize my expenses for a given week, a month, or year and display it as the section header title for example : (Oct 1- Oct 7, 2012) and it shows expenses amount and related stuff according to that particular week. Two buttons are provided in that view, if I would press the right button, it will increment the week by a week (Oct 1- Oct 7, 2012 now shows Oct8 - Oct 15, 2012) and similarly the left button would decrement the week by a week.

How would I accomplish that? I am trying the following code - doesn't work.

- (void)weekCalculation
{
   NSDate *today = [NSDate date];  // present date (current date)

   NSCalendar* calendar = [NSCalendar currentCalendar];
   NSDateComponents* comps = [calendar components:NSYearForWeekOfYearCalendarUnit |NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit fromDate:today];

   [comps setWeekday:1]; // 1: Sunday
   firstDateOfTheWeek = [[calendar dateFromComponents:comps] retain];
   [comps setWeekday:7]; // 7: Saturday
   lastDateOfTheWeek = [[calendar dateFromComponents:comps] retain];

   NSLog(@" first date of week =%@", firstDateOfTheWeek);
   NSLog(@" last date of week =%@", lastDateOfTheWeek);

   firstDateOfWeek = [dateFormatter stringFromDate:firstDateOfTheWeek];
   lastDateOfWeek = [dateFormatter stringFromDate:lastDateOfTheWeek];

}

Code for incrementing date -

- (IBAction)showNextDates:(id)sender
{
   int addDaysCount = 7;

   NSDateComponents *dateComponents = [[[NSDateComponents alloc] init] autorelease];
   [dateComponents setDay:addDaysCount];

   NSDate *newDate1 = [[NSCalendar currentCalendar]
                    dateByAddingComponents:dateComponents
                    toDate:firstDateOfTheWeek options:0];

   NSDate *newDate2 = [[NSCalendar currentCalendar]
                    dateByAddingComponents:dateComponents
                    toDate:lastDateOfTheWeek options:0];

   NSLog(@" new dates =%@ %@", newDate1, newDate2);

}

Suppose the week shows like this (Nov4, 2012 - Nov10, 2012) and I press the increment button, I see in the console, date changes to Nov11,2012 and Nov.17, 2012 which is right but if I press the increment button again, it shows the same date again (Nov 11, 2012 and Nov.17, 2012).

Please help me out here.

Angad Manchanda
  • 183
  • 5
  • 17
  • Your firstDateOfWeek and lastDateOfWeek are string and not dates. When you are using in [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:firstDateOfTheWeek options:0];, you need to convert to dates. – iDev Nov 09 '12 at 08:06
  • @ACB you read it wrong. They are dates only. Read it carefully Sir. – Angad Manchanda Nov 09 '12 at 08:07
  • @ACB Do you think this code should increment the date by a week, no matter how many times the increment button is pressed ? – Angad Manchanda Nov 09 '12 at 08:08
  • Oh okay. firstDateOfWeek and lastDateOfTheWeek looks confusing. In that case can you print lastDateOfTheWeek and check what is the date before incrementing again? – iDev Nov 09 '12 at 08:09
  • NSDate *today = [NSDate date]; // present date (current date) NSDateComponents* comps = [calendar components:NSYear..Unit fromDate:today]; So it will always calculate from today's week right? if I am correct you should switch to new date here itself. – iDev Nov 09 '12 at 08:11
  • Let me correct and post then.. – iDev Nov 09 '12 at 08:13
  • @ACB I print them and it shows that lastDateOfTheWeek is Nov.10, 2012 and when I increment, the date becomes 17 Nov 2012. I press the increment button again and it prints the same results. Does the above code looks right to you? – Angad Manchanda Nov 09 '12 at 08:13
  • @ACB You make sense. Please post the right code. Thanks man. – Angad Manchanda Nov 09 '12 at 08:14
  • Check my answer and let me know in case of any issues. – iDev Nov 09 '12 at 08:15
  • @ACB Shouldn't I include 2 date properties because I have two dates, right. self.currentDate = newDate1; I would probably need to add another date variable, right? – Angad Manchanda Nov 09 '12 at 08:23
  • No, basically all you need to know is the sunday corresponding to the given date. So you can use any of them to get that. When you are incrementing by 7 days, sunday of this week becomes sunday of next week. So you will ideally get the same day as sunday from week calculation and then when you calculate it will add 7 more days to that get its next week. Since you already got sunday, saturday of that week also will be automatically calculated by week calculation method. Try it out. – iDev Nov 09 '12 at 08:26

2 Answers2

2

Declare currentDate as an @property in your class. And try this.

@property(nonatomic, retain) NSDate *currentDate;

Initially set

self.currentDate = [NSDate date];

before calling this method.

- (void)weekCalculation
{
   NSCalendar* calendar = [NSCalendar currentCalendar];
   NSDateComponents* comps = [calendar components:NSYearForWeekOfYearCalendarUnit |NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit fromDate:self.currentDate];

   [comps setWeekday:1]; // 1: Sunday
   firstDateOfTheWeek = [[calendar dateFromComponents:comps] retain];
   [comps setWeekday:7]; // 7: Saturday
   lastDateOfTheWeek = [[calendar dateFromComponents:comps] retain];

   NSLog(@" first date of week =%@", firstDateOfTheWeek);
   NSLog(@" last date of week =%@", lastDateOfTheWeek);

   firstDateOfWeek = [dateFormatter stringFromDate:firstDateOfTheWeek];
   lastDateOfWeek = [dateFormatter stringFromDate:lastDateOfTheWeek];

}

Once the view is loaded self.currentDate value should be updated from showNextDates. Make sure it is not getting reset anywhere else.

- (IBAction)showNextDates:(id)sender
{
   int addDaysCount = 7;

   NSDateComponents *dateComponents = [[[NSDateComponents alloc] init] autorelease];
   [dateComponents setDay:addDaysCount];

   NSDate *newDate1 = [[NSCalendar currentCalendar]
                    dateByAddingComponents:dateComponents
                    toDate:firstDateOfTheWeek options:0];

   NSDate *newDate2 = [[NSCalendar currentCalendar]
                    dateByAddingComponents:dateComponents
                    toDate:lastDateOfTheWeek options:0];

   NSLog(@" new dates =%@ %@", newDate1, newDate2);

   self.currentDate = newDate1;

}
iDev
  • 23,310
  • 7
  • 60
  • 85
  • No, this doesn't work. When I press the increment button, first time, the date changes to 11 nov 2012 - 17 nov 2012, that's right but when I again press the button second time, it displays the same date again. – Angad Manchanda Nov 09 '12 at 08:40
  • What is printing in NSLog of first date of week ? is there any chance that you are restting currentDate? Also try with self.currentDate = newDate2; – iDev Nov 09 '12 at 08:42
  • It doesn't work at all. See this output: 2012-11-09 00:48:58.650 XpenseTrack[52798:c07] first date of week =2012-11-04 07:00:00 +0000 2012-11-09 00:48:58.650 XpenseTrack[52798:c07] last date of week =2012-11-10 08:00:00 +0000 2012-11-09 00:49:03.678 XpenseTrack[52798:c07] self current date = 2012-11-11 08:00:00 +0000 2012-11-17 08:00:00 +0000 2012-11-09 00:49:06.206 XpenseTrack[52798:c07] self current date = 2012-11-11 08:00:00 +0000 2012-11-17 08:00:00 +0000 2012-11-09 00:49:08.972 XpenseTrack[52798:c07] self current date = 2012-11-11 08:00:00 +0000 2012-11-17 08:00:00 +0000 – Angad Manchanda Nov 09 '12 at 08:49
  • It prints the same date over and over after pressing the increment button. – Angad Manchanda Nov 09 '12 at 08:49
  • Where is the NSLog for "new Dates = "? What are the two new dates after adding 7? Can you check while setting currentDate = newDate1, is it setting the next week's sunday there? – iDev Nov 09 '12 at 08:54
  • Those were the new dates only I printed.It seems to be confusing to me. – Angad Manchanda Nov 09 '12 at 08:58
  • there is another answer posted to this question, but while incrementing, it increments the date by 7, that's right. But I need to increment a week. – Angad Manchanda Nov 09 '12 at 09:00
  • I searched for that word and I cant locate it. Are you sure that you copy pasted exactly the same code in my answer? – iDev Nov 09 '12 at 09:01
  • I got it to work. I actually had to call [self weekCalculation] method inside these increment and decrement button actions. Now, it's working perfectly. – Angad Manchanda Nov 09 '12 at 09:06
  • @AngadManchanda, Yes you have to call that to update the get the new sunday and saturday. I thought that was already done. Anyways thanks for accepting. If it helped please click on the vote up(up arrow) as well. Actually I tried this code my self and I am getting it properly. – iDev Nov 09 '12 at 09:09
  • perfect. Please look into this last issue. You have been a great help so far. http://stackoverflow.com/questions/13302063/nsfetchedresultscontroller-with-section-names – Angad Manchanda Nov 09 '12 at 09:10
1

I had needed similar thing in one of my old projects and achieved it via the code below. It sets this weeks date to an NSDate variable and adds/removes 7 days from day component in each button click. Here is the code:

NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
NSDate *date = [NSDate date];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit|NSWeekdayCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)  fromDate:date ];
//
[components setDay:([components day] - ([components weekday] )+2)];
self.currentDate = [calendar dateFromComponents:components];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"dd.MM.yyyy HH:mm:ss";
self.datelabel.text = [formatter stringFromDate:self.currentDate];

The code above calculates this week start and sets it to currentDate variable. I Have two UIButtons with UIActions named prevClick and nextClick which calls the method that sets the next or previous weekstart:

- (IBAction)prevClick:(id)sender {
[self addRemoveWeek:NO];

}

-(void)addRemoveWeek:(BOOL)add{
NSCalendar *calendar = [NSCalendar currentCalendar];
[calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
NSDateComponents *components = [calendar components:(NSYearCalendarUnit|NSWeekdayCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)  fromDate:self.currentDate ];
components.day = add?components.day+7:components.day-7;
self.currentDate = [calendar dateFromComponents:components];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"dd.MM.yyyy HH:mm:ss";
self.datelabel.text = [formatter stringFromDate:self.currentDate];

}

- (IBAction)nextClk:(id)sender {
[self addRemoveWeek: YES];

}

Alessandro Minoccheri
  • 35,521
  • 22
  • 122
  • 171
madiden
  • 11
  • 2
  • @Alessandro The code which you wrote basically adds 7 days to the date when I press the increment button. What I want is that the increment button should increment my start date of the week and also the end date of the week by 7 days. like my label displays :(Oct 1, 2012 - Oct 7, 2012). After the increment button action, the label should display (Oct 8, 2012 - Oct 15, 2012). How would I accomplish that? – Angad Manchanda Nov 09 '12 at 08:45
  • @AlessandroMinoccheri my bad. sorry – Angad Manchanda Nov 09 '12 at 08:50
  • @madiden The code which you wrote basically adds 7 days to the date when I press the increment button. What I want is that the increment button should increment my start date of the week and also the end date of the week by 7 days. like my label displays :(Oct 1, 2012 - Oct 7, 2012). After the increment button action, the label should display (Oct 8, 2012 - Oct 15, 2012). How would I accomplish that? – Angad Manchanda Nov 09 '12 at 08:50