Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find if an NSDate is within a specified range?

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...

like image 691
Gup3rSuR4c Avatar asked Apr 07 '11 01:04

Gup3rSuR4c


People also ask

How do you check if date is within a certain range in Javascript?

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.

How do you check whether a date is valid or not in Swift?

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.


2 Answers

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")
}
like image 82
ughoavgfhw Avatar answered Sep 30 '22 20:09

ughoavgfhw


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 ;^))

like image 40
Mark Kuric Avatar answered Sep 30 '22 19:09

Mark Kuric