Reputation: 866
I need to take a stored NSDate and reliably determine whether it falls within the current moment's hour, day or week. I seem to have hacked together a solution, but not having solved this problem before, am not entirely confident that it's a reliable one.
Will this survive user-set 12 vs 24 hour time? the date formatting guide indicates that this user setting can lead to some unanticipated date behavior: "In iOS, the user can override the default AM/PM versus 24-hour time setting. This may cause NSDateFormatter to rewrite the format string you set."
What about the basic code pattern for this problem? Does this code seem to reliably serve its purpose? I hate to post a "check my code" sort of question, but it's an unfamiliar-enough problem to me, and tricky enough to rigorously test, that it seemed justified. NSDateFormatter is also relatively new to me; another motivation for the question.
NOTE: The main source of my nervousness is that converting dates to strings and then doing a string compare seems an inherently fragile method of solving this problem. But it's the best I could come up with.
Quick reference: the dateFormat
s I used for each of the three cases were:
dateFormat = @"yyyyMMddHH"; // For "this hour" check
dateFormat = @"yyyyMMdd"; // For "today" check
dateFormat = @"yyyyww"; // For "this week" check
Thanks! Code Follows:
- (BOOL)didThisCycle {
// Case 1: hourly; Case 2: daily; Case 3: weekly
BOOL did = NO;
NSDate *now = [NSDate date];
NSDate *lastDid = [self.didDates lastObject];
if (![lastDid isKindOfClass:[NSDate class]]) { // Crash protection
return NO;
}
int type = [self.goalType intValue];
switch (type) {
case 1:
{
// If hourly check hour
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
formatter.dateFormat = @"yyyyMMddHH";
NSString *nowString = [formatter stringFromDate:now];
NSString *lastDidString = [formatter stringFromDate:lastDid];
if ([nowString isEqualToString:lastDidString]) {
did = YES;
} else {
did = NO;
}
break;
}
case 2:
{
// If daily check day
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
formatter.dateFormat = @"yyyyMMdd";
NSString *nowString = [formatter stringFromDate:now];
NSString *lastDidString = [formatter stringFromDate:lastDid];
if ([nowString isEqualToString:lastDidString]) {
did = YES;
} else {
did = NO;
}
break;
}
case 3:
{
// If weekly check week
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
formatter.dateFormat = @"yyyyww";
NSString *nowString = [formatter stringFromDate:now];
NSString *lastDidString = [formatter stringFromDate:lastDid];
if ([nowString isEqualToString:lastDidString]) {
did = YES;
} else {
did = NO;
}
break;
}
default:
{
did = NO;
break;
}
}
return did;
}
Upvotes: 4
Views: 1015
Reputation: 57139
Use the NSDateComponents class, like so:
NSDate *someDate = // whatever
NSDate *now = [NSDate date];
NSDateComponents *thenComponents = [[NSCalendar currentCalendar] components:NSHourCalendarUnit|NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:someDate];
NSDateComponents *nowComponents = [[NSCalendar currentCalendar] components:NSHourCalendarUnit|NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:now];
if([thenComponents year] == [nowComponents year] && [thenComponents month] == [nowComponents month] && [thenComponents day] == [nowComponents day] && [thenComponents hour] == [nowComponents hour])
{
// hooray
}
Remove the “hour” component if you just want to check the day, or remove both that and “day” (and replace with NSWeekCalendarUnit
and the -week
method) to check the week.
Upvotes: 7