I am trying to calculate whether any of my Address Book's contacts have a birthday in the next 10 days. There's plenty of code on line to compare dates, but I only want to compare day and month. For example, if a contact was born 05/01/1960 (and assuming today is 04/24/2011), then I only want to calculate that there are only six days till their birthday. Help appreciated.
3 Answers
Change the birthday to this year (or next year if the birthday was already in this year) and calculate with NSDateComponents and NSCalendar.
Looks a bit complicated, but you could do it like this:
NSDate *birthDay = ... // [calendar dateFromComponents:myBirthDay];
NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents *thisYearComponents = [calendar components:NSYearCalendarUnit fromDate:[NSDate date]];
NSDateComponents *birthDayComponents = [calendar components:NSMonthCalendarUnit|NSDayCalendarUnit fromDate:birthDay];
[birthDayComponents setYear:[thisYearComponents year]];
NSDate *birthDayThisYear = [calendar dateFromComponents:birthDayComponents];
NSDateComponents *difference = [calendar components:NSDayCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
if ([difference day] < 0) {
// this years birthday is already over. calculate distance to next years birthday
[birthDayComponents setYear:[thisYearComponents year]+1];
birthDayThisYear = [calendar dateFromComponents:birthDayComponents];
difference = [calendar components:NSDayCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
}
NSLog(@"%i days until birthday", [difference day]);

- 89,811
- 20
- 225
- 247
-
Fantastic! Thanks fluchtpunkt. This works perfectly. Who would have thought something so simple needed this amount of work. – Jeremy Apr 24 '11 at 18:39
-
Everything that is date related needs a huge amount of code if you want to do it right. That's why there are so many bugs with timezones, daylight saving, leap years and so on. (Yes I look at you 86400 users.) We can feel happy that we have NSDateComponents and NSCalendar, otherwise you probably would need 20 times more code. – Matthias Bauch Apr 24 '11 at 18:47
-
Oh and btw, don't remove the `if ([difference day] < 0)` part, even if you think you are not interested in next years birthdays. Actually you are interested, at least for the last 10 days of a year for birthdays that happen in the first 10 days of a year. Took me a while to figure that one out. – Matthias Bauch Apr 24 '11 at 18:50
Once you have retrieved your contact's birthdate:
ABAddressBook get birthday property
you need to adjust the year component:
NSDate - Changing the year value
Then, you can compute the number of days till her birthday:
Use the below NSDate function with your contact NSDate
.
- (NSTimeInterval)timeIntervalSinceNow
The above function returns the interval between the receiver and the current date and time.
NSTimeInterval interval = [date1 timeIntervalSinceNow:myContactDate];
NSTimeInterval
is the elapsed time in seconds (expressed as a floating point number). You could then divide by 86400, which is the number of seconds in a day and round to the nearest integer.
NSInteger days = interval / 86400;
Now you have number of days...
EDITED:
You could also use the NSCalendar
and NSDateComponents
to only get the day component between two date.
- (NSDateComponents *)components:(NSUInteger)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSUInteger)opts
Use the below code as reference. (Taken From Apple Documentation for NSCalendar)
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *startDate = ...;
NSDate *endDate = ...;
unsigned int unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *comps = [gregorian components:unitFlags fromDate:startDate toDate:endDate options:0];
int months = [comps month];
int days = [comps day];

- 31,697
- 9
- 72
- 76