How to group NSDate objects by day? - iphone

I'm setting a timeStamp property for an object. Right now I'm just using [NSDate date]. The user might create 10 objects per day. But in the UI, I want to drop them by date. So each day will show all the objects that were created for that day. How can I do this? Right now it's trying to match the date and time, etc.
Example:
Obj1 - 2/5/12 5pm
Obj2 - 2/5/12 12pm
Obj3 - 2/4/12 6pm
Obj4 - 2/1/12 1pm
I need to be able to group those by day, one for 2/5, 2/4, and 2/1.

You can use the NSDateComponents class to be able to directly access the day, month, and year of an NSDate instance.
NSDate *someDate = [NSDate date];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:someDate];
NSLog(#"Year: %d", [components year]);
NSLog(#"Month: %d", [components month]);
NSLog(#"Day: %d", [components day]);
Here's an NSDateComponents comparison method:
- (BOOL)isFirstCalendarDate:(NSDateComponents *)first beforeSecondCalendarDate:(NSDateComponents *)second
{
if ([first year] < [second year]) {
return YES;
} else if ([first year] == [second year]) {
if ([first month] < [second month]) {
return YES;
} else if ([first month] == [second month]) {
if ([first day] < [second day]) {
return YES;
}
}
}
return NO;
}
I haven't tested the NSDateComponents comparison method; it would benefit from unit testing.

Your question is formulated rather broadly. To get the date part of an NSDate object, as an NSString, you could use:
NSDate *dateIn = [NSDate date];
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
[fmt setDateFormat:#"yyyy-MM-dd"];
NSString *stringOut = [fmt stringFromDate:dateIn];
[fmt release];
You can easily change the date format. If you would call this code often (e.g. in a loop) you might want to allocate and set up the date formatter only once.

Related

Check if current date is between two given dates [duplicate]

This question already has answers here:
How to Check if an NSDate occurs between two other NSDates
(10 answers)
Closed 9 years ago.
I want to check if current date is between two given dates. I do the following
NSDate *now = [NSDate new];
NSLog(#"Now is %#",now);
NSCalendar *myCalendar = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];
NSDateComponents* components = [myCalendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date]];
[components setYear:2013];
[components setMonth:06];
[components setDay:28];
[components setHour:5];
[components setMinute:00];
NSDate *startDate1 = [myCalendar dateFromComponents:components];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.timeZone = [NSTimeZone localTimeZone];
formatter.dateFormat = #"yyyy-MM-dd HH:mm:ss";
NSLog(#"start dateeee is %#",startDate1);
NSDateComponents* components2 = [myCalendar components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date]];
[components2 setYear:2013];
[components2 setMonth:06];
[components2 setDay:29];
[components2 setHour:4];
[components2 setMinute:59];
NSDate *endDate1 = [myCalendar dateFromComponents:components];
NSLog(#"end date is %#",endDate1)
;
Now I have created 2 dates Startdate1 and endDate1. For to check if the current date is between those to dates I am doing this.
NSComparisonResult result1 = [now compare:startDate1];
NSComparisonResult result2 = [now compare:endDate1];
if (result2 == NSOrderedSame && result1 == NSOrderedSame ) {
NSLog(#"HELL YEAH! ");
}
But I never get a HELL YEAH ??
NOTE: I have set my iPhone datetime to a time between the start and enddate. Also here are my LOGS:
2013-06-29 11:11:48.727 Genk on stage[2205:907] Now is 2013-06-29 09:11:48 +0000
2013-06-29 11:11:48.728 Genk on stage[2205:907] start dateeee is 2013-06-28 03:00:00 +0000
2013-06-29 11:11:48.729 Genk on stage[2205:907] end date is 2013-06-28 03:00:00 +0000
Your logic is flawed. The return value NSOrderedSame means that two values compared equal. That's not what you want. Instead, you want to check if the first date comes before the current date and the second one comes after it:
if (result1 == NSOrderedAscending && result2 == NSOrderedDescending)
is what you should write.
change your code to
if (result2 == NSOrderedDescending && result1 == NSOrderedAscending ) {
NSLog(#"HELL YEAH! ");
}
This might solve your problem
Happy coding :)
NSDate * now;.....
NSDate * endDate1;......
if ([now compare: endDate1] == NSOrderedDescending) {
NSLog(#"now is later than endDate1");
} else if ([now compare: endDate1] == NSOrderedAscending) {
NSLog(#"now is earlier than endDate1");
} else {
NSLog(#"dates are the same");
}
You can use the following code.
NSTimeInterval fromTime = [startDate1 timeIntervalSinceReferenceDate];
NSTimeInterval toTime = [endDate1 timeIntervalSinceReferenceDate];
NSTimeInterval currTime = [[NSDate date] timeIntervalSinceReferenceDate];
if(currTime>fromTime && currTime<toTime)
{
//current time lies between the two dates
}
You can check this using this :
- (BOOL)yourDate:(NSDate *)date inRangeFirstDate:(NSDate *)startDate lastDate:(NSDate *)endDate {
return [date compare:startDate] == NSOrderedDescending &&
[date compare:endDate] == NSOrderedAscending;
}
If it returns YES then yourDate lies between the startDate and endDate else it returns NO.
Hope it helps you

How to implement previous next day buttons to change the date in iphone

As shown in the above page I have a date (current date by default) on a label. In the format of MM dd.
I have two buttons to change the date next day & the previous day.
How should I implement change the date by using these buttons?
Any tutorial / advice (I don't think there is any involvement of datepicker in this)
Use these two functions to get previous date and next date and then use the returned date and use only month and year to display on your label.
+ (NSDate *) getDate:(NSDate *)fromDate daysAgo:(NSUInteger)days
{
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
dateComponents.day = -1*days;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *previousDate = [calendar dateByAddingComponents:dateComponents
toDate:fromDate
options:0];
[dateComponents release];
return previousDate;
}
+ (NSDate *) getDate:(NSDate *)fromDate daysAhead:(NSUInteger)days
{
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
dateComponents.day = days;
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *previousDate = [calendar dateByAddingComponents:dateComponents
toDate:fromDate
options:0];
[dateComponents release];
return previousDate;
}
Try these methods
- (NSDate *) dateByAddingDays: (int) dDays : (NSDate*)presntdate
{
NSTimeInterval aTimeInterval = [presntdate timeIntervalSinceReferenceDate] + 86400 * dDays;
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
return newDate;
}
- (NSDate *) dateBySubtractingDays: (int) dDays : (NSDate*)presntdate
{
return [self dateByAddingDays: dDays*-1 :presntdate];
}

Check if NSDate is in this week or next week

there is a way to check if an NSDate is this week or is next week?
i know that today is:
[NSDate date]
and then how i can do?
Use NSDateComponents, something like this:
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *today = [NSDate date];
NSDateComponents *todaysComponents =
[gregorian components:NSWeekCalendarUnit fromDate:date];
NSUInteger todaysWeek = [todaysComponents week];
NSDate *anotherDate = [NSDate date];
NSDateComponents *otherComponents =
[gregorian components:NSWeekCalendarUnit fromDate:anotherDate];
NSUInteger anotherWeek = [otherComponents week];
if(todaysWeek==anotherWeek){
NSLog(#"another date is this week");
}else if(todaysWeek+1==anotherWeek){
NSLog(#"another date is next week")
}
You can also use other components like month or year to be completely sure.
NOTE: Don't use timeIntervals. By using NSDateComponents you ignore the hour, minutes and seconds. I think you want that.
pass the 2 dates to this method:
- (BOOL) isSameWeekAsDate: (NSDate *) aDate andDate:(NSDate *) bDate
{
NSDateComponents *components1 = [[NSCalendar currentCalendar] components:(NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekdayCalendarUnit | NSWeekdayOrdinalCalendarUnit) fromDate:aDate];
NSDateComponents *components2 = [[NSCalendar currentCalendar] components:(NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekdayCalendarUnit | NSWeekdayOrdinalCalendarUnit) fromDate:bDate];
if ([components1 week] != [components2 week]) return NO;
//return (abs([self timeIntervalSinceDate:aDate]) < 604800); // ops, forgot to change "self" with parameter "bDate":
return (abs([bDate timeIntervalSinceDate:aDate]) < 604800);
}
EDIT:
call it with 2 dates of different years:
[components setDay:31];
[components setMonth:12];
[components setYear:2010];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date1 = [gregorian dateFromComponents:components];
// second date (SATURDAY -of the same week, other year...)
[components setDay:1];
[components setMonth:1];
[components setYear:2011];
NSDate *date2 = [gregorian dateFromComponents:components];
if ([self isSameWeekAsDate:date1 andDate:date2]) {
NSLog(#"Same Week!");
}else{
NSLog(#"OTHER WEEK!");
}
I'am adding my solution (implemented as an NSDate category), which doesn't use week, which is deprecated in iOS7, iOS8
- (NSDate *)firstDateOfWeek {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *startOfWeek;
[calendar rangeOfUnit:NSCalendarUnitWeekOfYear startDate:&startOfWeek interval:NULL forDate:self];
return startOfWeek;
}
- (BOOL)isSameWeekWithDate:(NSDate *)date {
if (ABS(self.timeIntervalSince1970 - date.timeIntervalSince1970) > (7 * 24 * 60 * 60)) {
return NO;
}
return ([[self firstDateOfWeek] timeIntervalSince1970] == [[date firstDateOfWeek] timeIntervalSince1970]);
}
- (BOOL)isThisWeek {
return [self isSameWeekWithDate:[NSDate new]];
}
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:NSWeekCalendarUnit fromDate:yourDate];
NSInteger week = [components week]; // here your have a Integer with the weeknr of yourDate
components = [cal components:NSWeekCalendarUnit fromDate:[NSDate date]];
weekToday = [components week]; // here your have a Integer with the weeknr of today
The rest you should be able to do.
It might get another brainwork when it comes to the last week in year.
Clear?
NOTE: this calculates the idea of "week" using a Sunday-Saturday concept of week.
To calculate the current day of the week use the following from here:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *weekdayComponents =[gregorian components:NSWeekdayCalendarUnit fromDate:dateOfInterest];
NSInteger weekday = [weekdayComponents weekday];
// weekday 1 = Sunday for Gregorian calendar
[gregorian release];
The rest should be pretty trivial. Get the current date and the date from your NSDate. Find the start and end dates using the day and the date (if today is monday then date - 1 day is the first day of the week etc). Figure out which week the date is in.
For iOS 7 and above, you have to replace NSWeekCalendarUnit with NSCalendarUnitWeekOfYear
- (NSInteger)thisW:(NSDate *)date
{
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *todaysComponents = [gregorian components:NSCalendarUnitWeekOfYear fromDate:[NSDate date]];
NSUInteger todaysWeek = [todaysComponents weekOfYear];
NSDateComponents *otherComponents = [gregorian components:NSCalendarUnitWeekOfYear fromDate:date];
NSUInteger datesWeek = [otherComponents weekOfYear];
//NSLog(#"Date %#",date);
if(todaysWeek==datesWeek){
//NSLog(#"Date is in this week");
return 1;
}else if(todaysWeek+1==datesWeek){
//NSLog(#"Date is in next week");
return 2;
} else {
return 0;
}
}
Forget about date components, you have to tweak lots of things (check if it's the last week of the year, check if Sunday is the beginning of the week...) and is prone to errors and spaghetti code.
This solves your issue and is extended to detect "last week", "previous weeks", "this week", "next week" and "later weeks"
-(EventWeekRange)numberOfWeeksFromTodayToEvent:(NSDate *)eventDate {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSComparisonResult comparison = [calendar compareDate:[NSDate date] toDate:eventDate toUnitGranularity:NSCalendarUnitWeekOfYear];
if (comparison == NSOrderedSame) {
return RangeThisWeek;
} else if (comparison == NSOrderedAscending) { // The event date is in the future
// Advance today's date one week to check if this new date is in the same week as the event
NSDate *todaysNextWeek = [[NSDate date]dateByAddingTimeInterval:60*60*24*7];
if ([calendar compareDate:todaysNextWeek toDate:eventDate toUnitGranularity:NSCalendarUnitWeekOfYear] == NSOrderedSame) {
return RangeNextWeek;
} else {
return RangeLater;
}
} else { // The event date is in the past
// Advance the event's date one week to check if this new date is in the same week as today
NSDate *eventsNextWeek = [eventDate dateByAddingTimeInterval:60*60*24*7];
if ([calendar compareDate:eventsNextWeek toDate:[NSDate date] toUnitGranularity:NSCalendarUnitWeekOfYear] == NSOrderedSame) {
return RangeLastWeek;
} else {
return RangeEarlier;
}
}
}

iPhone: method to calculate days till next birthday not accurate --?

Here's a puzzler. I use the following to calculate the number of days between today's date and an upcoming birthday:
-(int) daysTillBirthday: (NSDate*)aDate {
// check to see if valid date was passed in
//NSLog(#"aDate passed in is %#",aDate);
if (aDate == nil) {
//NSLog(#"aDate is NULL");
return -1; // return a negative so won't be picked in table
}
//** HOW MANY DAYS TO BDAY
NSDate *birthDay = aDate; // [calendar dateFromComponents:myBirthDay];
//NSLog(#"birthDay: %#, today: %#",birthDay, [NSDate date]);
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];
//NSLog(#"birthDayThisYear: %#",birthDayThisYear);
NSDateComponents *differenceHours = [calendar components:NSHourCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
NSDateComponents *differenceDays = [calendar components:NSDayCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
// NSLog(#"difference days: %i, hours %i",[differenceDays day],[differenceHours hour]);
//*** I added this to try and correct the "error" ***
if ([differenceDays day] == 0) { // is it today, or tomorrow?
if (([differenceHours hour] <= 0) && ([differenceHours hour] >= -24)) { // must be today
//NSLog(#"TODAY");
return (0);
[calendar release];
}else if (([differenceHours hour] >= 0) && ([differenceHours hour] <= 24)) {
//NSLog(#"TOMORROW");
return (1);
[calendar release];
}
}
if ([differenceDays day] < 0) {
// this years birthday is already over. calculate distance to next years birthday
[birthDayComponents setYear:[thisYearComponents year]+1];
birthDayThisYear = [calendar dateFromComponents:birthDayComponents];
differenceDays = [calendar components:NSDayCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
}
return ([differenceDays day]);
[calendar release];
}
Everything works, but the results are not accurate! I often find that birthdays that are close to today, but one day apart, result in [differenceDays day] being the same! i.e. if today is 6/6/2011 and I have two birthdays, one on 6/7/2011 and another 6/8/2011, then they are both shown as 1 day away!
Anyone have any better methods for accurately calculating this, or can spot the problem?
Many thanks.
NSCalendar provides a much easier way to do this:
NSDate *birthday = ...; // the birthday
NSDate *today = [NSDate date];
NSCalendar *c = [NSCalendar currentCalendar];
NSInteger birthdayDayOfYear = [c ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:birthday];
NSInteger todayDayOfYear = [c ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:today];
NSInteger different = birthdayDayOfYear - todayDayOfYear;
Basically, we're figuring out how far into the year today and the target date are (ie, today [5 Jun] is the 156th day of the year), and then subtract them to figure out how many days are in between them.
This method, of course, relies on the assumption that the target date is in the same year as the current date. I think it'd be fairly easy to work around that, however.
Another, even easier way to do this that will account for multi-year differences is like this:
NSDateComponents *d = [[NSCalendar currentCalendar] components:NSDayCalendarUnit fromDate:today toDate:birthday options:0];
NSInteger difference = [d day];
If you need to make sure that the birthday is in the future, that's easily accomplished as well:
NSDateComponents *year = [[[NSDateComponents alloc] init] autorelease];
NSInteger yearDiff = 1;
NSDate *newBirthday = birthday;
while([newBirthday earlierDate:today] == newBirthday) {
[year setYear:yearDiff++];
newBirthday = [[NSCalendar currentCalendar] dateByAddingComponents:year toDate:birthday options:0];
}
//continue on with the 2-line calculation above, using "newBirthday" instead.
update I updated the loop above to always increment from the original date n years at a time, instead of year-by-year. If someone is born on 29 Feb, incrementing by one year would yield 1 Mar, which would be wrong once you got to a leap year again. By jumping from the original date each time, we don't have this issue.
I do the exact same thing in one of my apps. Here is how I do it:
//This is the date your going to - in your case the birthday - note the format
NSString *myDateAsAStringValue = #"20110605";
// Convert string to date object
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyyMMdd"];
NSDate *newDate = [dateFormat dateFromString:myDateAsAStringValue];
NSDateComponents *dateComp = [[NSDateComponents alloc] init];
NSCalendar *Calander = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps=[[NSDateComponents alloc] init];
unsigned int unitFlags = NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
dateComp = [Calander components:unitFlags fromDate:[NSDate date]];
[dateFormat setDateFormat:#"dd"];
[comps setDay:[[dateFormat stringFromDate:[NSDate date]] intValue]];
[dateFormat setDateFormat:#"MM"];
[comps setMonth:[[dateFormat stringFromDate:[NSDate date]] intValue]];
[dateFormat setDateFormat:#"yyyy"];
[comps setYear:[[dateFormat stringFromDate:[NSDate date]] intValue]];
[dateFormat setDateFormat:#"HH"];
[comps setHour:05];
[dateFormat setDateFormat:#"mm"];
[comps setMinute:30];
NSDate *currentDate=[Calander dateFromComponents:comps];
dateComp = [Calander components:unitFlags fromDate:newDate];
[dateFormat setDateFormat:#"dd"];
[comps setDay:[[dateFormat stringFromDate:newDate] intValue]];
[dateFormat setDateFormat:#"MM"];
[comps setMonth:[[dateFormat stringFromDate:newDate] intValue]];
[dateFormat setDateFormat:#"yyyy"];
[comps setYear:[[dateFormat stringFromDate:newDate] intValue]];
[dateFormat setDateFormat:#"HH"];
[comps setHour:05];
[dateFormat setDateFormat:#"mm"];
[comps setMinute:30];
NSDate *reminderDate=[Calander dateFromComponents:comps];
NSTimeInterval ti = [reminderDate timeIntervalSinceDate:currentDate];
int days = ti/86400;
return days;
I think I have found a solution. Checking the output carefully, it appears to all come down to the difference in HOURS. For example: comparing today with tomorrow's date might end up being, say, 18 hours away. This results in [difference day] being set at 0 i.e. it thinks tomorrow is today because it is less than 24 hours away.
You can see the fix below. I take the number of hours e.g. 18 and divide by 24 (to get the number of days). In this case 18/24 = 0.75. I then round this up i.e. to "1." So while [difference days] thinks tomorrow is today, by rounding up the hours, you know it is in fact tomorrow.
-(int) daysTillBirthday: (NSDate*)aDate {
// check to see if valid date was passed in
//NSLog(#"aDate passed in is %#",aDate);
if (aDate == nil) {
//NSLog(#"aDate is NULL");
return -1; // return a negative so won't be picked in table
}
//** HOW MANY DAYS TO BDAY
NSDate *birthDay = aDate; // [calendar dateFromComponents:myBirthDay];
NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents *thisYearComponents = [calendar components:NSYearCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit fromDate:[NSDate date]];
NSDateComponents *birthDayComponents = [calendar components:NSMonthCalendarUnit|NSDayCalendarUnit fromDate:birthDay];
NSInteger timeNow = [thisYearComponents hour];
[birthDayComponents setYear:[thisYearComponents year]];
[birthDayComponents setHour:timeNow];
NSDate *birthDayThisYear = [calendar dateFromComponents:birthDayComponents];
//NSLog(#"today %#, birthday %#",[NSDate date],birthDayThisYear);
NSDateComponents *difference = [calendar components:NSDayCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
NSDateComponents *differenceHours = [calendar components:NSHourCalendarUnit fromDate:[NSDate date] toDate:birthDayThisYear options:0];
double daysFromHours = ((double)[differenceHours hour])/24; // calculate number of days from hours (and round up)
int roundedDaysFromHours = ceil(daysFromHours);
NSLog(#"daysFromHours %.02f, roundedDaysFromHours %i",daysFromHours,roundedDaysFromHours);
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]);
return (roundedDaysFromHours);
[calendar release];
}

Sort NSArray by NSDate, today

I have loaded item from core data in an NSMutableArray. Each item, when created, is given a due date, that the user choices.
How do I sort, so only the item that is due today is displayed?
Here is what I got so far:
NSPredicate *predicate = [NSPredicate predicateWithFormat: #"dueDate == %#", [NSDate date]];
[allObjectsArray filterUsingPredicate: predicate];
This code doesn't work however.
Thanks for any suggestions
How about you just calculate today at 00:00 and then tomorrow at 00:00 and then compare the dates in the predicate to those (>= and <). So all date objects must be within those two dates to be classed as being 'Today'. This requires you to only calculate 2 dates initially, no matter how many date objects are in your array.
// Setup
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *now = [NSDate date];
// Get todays year month and day, ignoring the time
NSDateComponents *comp = [cal components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:now];
// Components to add 1 day
NSDateComponents *oneDay = [[NSDateComponents alloc] init];
oneDay.day = 1;
// From date & To date
NSDate *fromDate = [cal dateFromComponents:comp]; // Today at midnight
NSDate *toDate = [cal dateByAddingComponents:oneDay toDate:fromDate options:0]; // Tomorrow at midnight
// Cleanup
[oneDay release]
// Filter Mutable Array to Today
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"dueDate >= %# && dueDate < %#", fromDate, toDate];
NSArray *filteredArray = [allObjectsArray filteredArrayUsingPredicate:predicate];
// Job Done!
The problem with using predicates is that if they use standard date comparison, it'll only return dates that are exactly the date and time of the given date. If you want "today" dates, you'll need to add a -isToday method somewhere (possible as an extension to NSDate), like this:
-(BOOL)dateIsToday:(NSDate *)aDate {
NSDate *now = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *nowComponents = [cal components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit
fromDate:now];
NSDateComponents *dateComponents = [cal components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit
fromDate:aDate];
return (([nowComponents day] == [dateComponents day]) &&
([nowComponents month] == [dateComponents month]) &&
([nowComponents year] == [dateComponents year]));
}
Once you have that, it's simple enough to find the ones that are today:
NSMutableArray *itemsDueToday = [NSMutableArray array];
for (MyItem *item in items) {
if ([self dateIsToday:[item date]) {
[itemsDueToday addObject:item];
}
}
// Done!
The method -filterUsingPredicate: only works on mutable arrays (of type NSMutableArray).
Try using the -filteredArrayUsingPredicate: method, instead:
NSString *formattedPredicateString = [NSString stringWithFormat:#"dueDate == '%#'", [NSDate date]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:formattedPredicateString];
NSArray *filteredArray = [allObjectsArray filteredArrayUsingPredicate:predicate];