Reputation: 9480
So, I'm having a difficult time (no pun intended) finding if an NSDate is within a specific range. Consider this: a scheduled visit between 5:00 PM and 6:00 PM. I want to find if the scheduled visit is within +/- 15 minutes of the current time. Thus my safe range is 4:45 PM to 6:15 PM. How can I find out if the scheduled visit is in or out of the range? Here's the code I've got so far, which doesn't work at all...
- (BOOL)isInScheduledRange {
// NSLog(@"Start: %f", [self.start timeIntervalSinceNow]);
// NSLog(@"End: %f", [self.end timeIntervalSinceNow]);
//
// if (([self.start timeIntervalSinceNow] >= -900) && ([self.end timeIntervalSinceNow] <= 3600)) {
// NSLog(@"In Range");
//
// return YES;
// }
//
NSDate *now = [[NSDate alloc] init];
// if ((([self.start timeIntervalSinceDate:now] >= -900) && ([self.start timeIntervalSinceDate:now] <= 900)) && (([self.end timeIntervalSinceDate:now] <= -900) && ([self.end timeIntervalSinceDate:now] >= 900))) {
// NSLog(@"In Range");
// }
NSLog(@"%@; %@; %@", now, self.start, self.end);
// NSLog(@"%@; %@", [self.start timeIntervalSinceDate:now], [self.end timeIntervalSinceDate:now]);
if ((([self.start timeIntervalSinceDate:now] >= -900) && ([self.start timeIntervalSinceDate:now] <= 0)) && (([self.end timeIntervalSinceDate:now] >= 0) && ([self.end timeIntervalSinceDate:now] <= 900))) {
NSLog(@"In Range");
}
return NO;
[now release];
}
I'd appreciate some help. I'm having difficulties with this time calculation.
On a separate note, I hate dealing with time no matter what platform I'm working with...
Upvotes: 6
Views: 1720
Reputation: 3919
This is a distance problem - you want to know if the current time is within 900 seconds of the target time. Compute distance problems by taking the absolute value of the difference between the two points. By taking the absolute value of the difference, the order of the two samples doesn't matter.
/**
* @brief Return YES if the current time is within 900 seconds of the meeting time (NSDate* time).
*/
-(BOOL)currentTimeIsWithin900SecondsOf:(NSDate*)time
{
NSDate* now = [NSDate date];
return fabs( [now timeIntervalSinceReferenceDate] - [time timeIntervalSinceReferenceDate] ) < 900;
}
Upvotes: 2
Reputation: 156
Here's some verbose (and silly) code that explains my approach to this problem
NSTimeInterval secondsBeforeStart = [self.start timeIntervalSinceNow];
if ( secondsBeforeStart > (15 * 60))
{
// The result for '[self.start timeIntervalSinceNow]' is positive as long
// as 'self.start' remains in the future. We're not in range until there
// are 900 seconds to go or less.
NSLog( @"Still time to chill.");
// More than fifteen minutes to go so return NO.
return NO;
}
else
{
NSLog( @"OMG did I miss it!!!");
NSTimeInterval secondsBeforeEnd = [self.end timeIntervalSinceNow];
if ( secondsBeforeEnd < -( 15 * 60))
{
// The result for '[self.end timeIntervalSinceNow]' is negative when
// 'self.end' is in the past.
// It's been more than 900 seconds since the end of the appointment
// so we've missed it.
NSLog( @"Ahhhhh!!!");
// More than 900 seconds past the end of the event so return NO.
return NO;
}
else
{
// We are somewhere between 900 seconds before the start and
// 900 seconds before the end so we are golden.
NSLog( @"Whew, we made it.");
return YES;
}
}
The way I would have coded it would have been
BOOL inRange = NO; // Assume we are not in the proper time range.
if ( [self.start timeIntervalSinceNow] <= ( 15 * 60))
{
// 'Now' is at least 900 seconds before the start time but could be later.
if ( [self.end timeIntervalSinceNow] >= -( 15 * 60))
{
// 'Now' is not yet 900 seconds past the end time.
inRange = YES
}
}
return inRange;
Note: I haven't actually compiled this but I'm pretty sure the logic is correct.
Finally, you did notice that your last two lines
return NO;
[now release];
}
would have created a memory leak. (Release and then return ;^))
Upvotes: 3
Reputation: 39905
You want to check if the start time is less than 900 seconds after the current time, and the end time is less than 900 seconds before the current time. timeIntervalSinceDate:
returns a positive number if the object it is called on is after the argument, you need to check for start <= 900 and end >= −900. Also, you could simplify your code by using timeIntervalSinceNow
instead of manually getting the current date and passing it to timeIntervalSinceDate:
. Finally, if you can assume (or previously ensured) that the start is before the end, then you don't need the two middle tests, as they will both have to be true for both of the others to be true.
if([self.start timeIntervalSinceNow] <= 900 && [self.end timeIntervalSinceNow] >= −900) {
NSLog(@"In range")
}
Upvotes: 6
Reputation: 58077
You need to create three NSDates. Then convert NSDates to time intervals using intervalSinceReferenceDate and compare those. You manually set up NSDates by using NSDateComponents.
Upvotes: 0