0

I am trying to determine if the current date is in fact three days or less from the end of the month. In other words, if I am in August, then I would like to be alerted if it is the 28,29,30, or 31st. If I am in February, then I would like to be notified when it is the 25,26,27, or 28 (or even 29). In the case of a leap year, I would be alerted from 26th onwards.

My problem is that I am not sure how to perform such a check so that it works for any month. Here is my code that I have thus far:

-(BOOL)monthEndCheck {

   NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay |  NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
   NSInteger day = [components day];
   NSInteger month = [components month];
   NSInteger year = [components year];

   if (month is 3 days or less from the end of the month for any month) {

     return YES;

   }  else {

     return NO;

   }

}

Because there are months with 28, 30, and 31 days, I would like a dynamic solution, rather than creating a whole series of if/else statements for each and every condition. Is there a way to do this?

halfer
  • 19,824
  • 17
  • 99
  • 186
syedfa
  • 2,801
  • 1
  • 41
  • 74

2 Answers2

3

This is how you get the last day of the month:

NSDate *curDate = [NSDate date];
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* comps = [calendar     components:NSYearCalendarUnit|NSMonthCalendarUnit|NSWeekCalendarUnit|NSWeekdayCalendarUnit     fromDate:curDate]; // Get necessary date components

// set last of month
[comps setMonth:[comps month]+1];
[comps setDay:0];
NSDate *tDateMonth = [calendar dateFromComponents:comps];
NSLog(@"%@", tDateMonth);

Source: Getting the last day of a month

EDIT (another source): How to retrive Last date of month give month as parameter in iphone

Now you can simply count from the current date. If < 3 do whatever you wanted to do.

Maybe something like this:

NSTimeInterval distanceBetweenDates = [date1 timeIntervalSinceDate:date2];
double timeInSecondsFor3Days = 280000; //Better use NSDateComponents here!
NSInteger hoursBetweenDates = distanceBetweenDates / timeInSecondsFor3Days;

However I did not test that^^

EDIT: Thanks to Aaron. Do NSDateComponents to calculate the time for three days instead!

Community
  • 1
  • 1
Akaino
  • 1,025
  • 6
  • 23
  • 3
    Three days don't always have 280,000 seconds. Better to do your math with `NSDateComponents` instead. – Aaron Brager Aug 18 '14 at 16:55
  • Thanks very much for your solution. Would I calculate the seconds for three days as: double timeInSecondsFor3Days = [components day];? – syedfa Aug 18 '14 at 18:18
  • 1
    That should get you at least one day, yes. Check Martins answer (below) he managed to do so with `NSDateComponents *comp = [cal components:NSCalendarUnitDay fromDate:startOfToday toDate:startOfNextMonth options:0];` – Akaino Aug 18 '14 at 18:39
2

First you have to compute the start of the current day (i.e. today at 00.00). Otherwise, the current day will not count as a full day when computing the difference between today and the start of the next month.

NSDate *now = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *startOfToday;
[cal rangeOfUnit:NSCalendarUnitDay startDate:&startOfToday interval:NULL forDate:now];

Computing the start of the next month can be done with rangeOfUnit:... (using a "statement expression" to be fancy :)

NSDate *startOfNextMonth = ({
    NSDate *startOfThisMonth;
    NSTimeInterval lengthOfThisMonth;
    [cal rangeOfUnit:NSCalendarUnitMonth startDate:&startOfThisMonth interval:&lengthOfThisMonth forDate:now];
    [startOfThisMonth dateByAddingTimeInterval:lengthOfThisMonth];
});

And finally the difference in days:

NSDateComponents *comp = [cal components:NSCalendarUnitDay fromDate:startOfToday toDate:startOfNextMonth options:0];
if (comp.day < 4) {
    // ...
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382