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...
To check if a date is between two dates: Use the Date() constructor to convert the dates to Date objects. Check if the date is greater than the start date and less than the end date.
The return value of a date generated by DateFormatter 's date(from:) method is an optional. If nil is returned the date is invalid, otherwise it's valid. A Date cannot be instantiated with an invalid date string that is outside of the realm of real calendar dates.
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")
}
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 ;^))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With