2

I want to check whether the date limit*(Ex:- 22/07/2013 2:30PM -22/07/2013 8:30PM )* comes with in another time limit*(Ex:- 22/07/2013 4:30PM -22/07/2013 6:30PM )* or not. I am completely new to this concept. Can anyone please tell me how to do this.

Any help will be highly appreciated

Below is the code I tried:

- (void)viewDidLoad
{
    [self isDateInterval:@"8/1/2013 8:30am" and:@"8/1/2013 8:40am" fallsWithin:@"8/1/2013 8:30am" and:@"8/1/2013 8:55am"];
    [super viewDidLoad];
}

-(BOOL)isDateInterval:(NSString*)startDate1 and:(NSString*)endDate1 fallsWithin:(NSString*)startDate2 and:(NSString*)endDate2
{
    BOOL isWithinrange;

    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];

    [formatter setDateFormat:@"dd/MM/yyyy hh:mmaa"];

    NSTimeInterval ti1 = [[formatter dateFromString:startDate1] timeIntervalSince1970];
    NSTimeInterval ti2 = [[formatter dateFromString:endDate1] timeIntervalSince1970];

    NSTimeInterval ti3 = [[formatter dateFromString:startDate2] timeIntervalSince1970];
    NSTimeInterval ti4 = [[formatter dateFromString:endDate2] timeIntervalSince1970];

    if( (ti3 > ti1 && ti3 < ti2) || (ti3 < ti1 && ti4 > ti1) )
    {
        //Date with in range
        isWithinrange=TRUE;
    }
    else
    {
        isWithinrange=FALSE;
        //Not with in range
    }

    return isWithinrange;
}

I want the output to be "isWithin" as because part of the time interval of one is coming into the other time interval

surendher
  • 1,374
  • 3
  • 26
  • 52
  • How are the dates stored? As pairs? You could use a predicate. – Wain Jul 27 '13 at 15:32
  • @Wain The date would be stored into SQLite. In format like MM/DD/YYYY Time:aa – surendher Jul 27 '13 at 15:34
  • Core data, or directly in SQLite? – Wain Jul 27 '13 at 15:36
  • @Wain It will be stored in SQLite and not in coredata – surendher Jul 27 '13 at 15:38
  • Ok, last clarification, you want to compare in a query or after the data has been extracted from the table? – Wain Jul 27 '13 at 15:39
  • @Wain i want to compare whether the selected time interval falls between the another time interval or not...The time would be MM/DD/YYYY time:aa – surendher Jul 27 '13 at 15:41
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/34295/discussion-between-surendher-and-wain) – surendher Jul 27 '13 at 15:45
  • 1
    You want to know whether the first time interval is _completely contained_ in the second, or just whether they _overlap somewhere_? For your example dates, the second time interval is completely contained within the first. Thus, they overlap. But 22/07/2013 2:30PM - 22/07/2013 5:30PM overlaps your second interval without containing it. Which are you trying to calculate? – jscs Jul 27 '13 at 18:25
  • @JoshCaswell yes, absolutely – surendher Jul 28 '13 at 12:36
  • Yes to _which_? There are two choices: completely contained, or just overlap. – jscs Jul 28 '13 at 18:41
  • @JoshCaswell It should show within range in following cases. Case 1:Strt Time 8/07/2013 2:00am endTime 8/07/2013 4:00am another interval Strt Time 8/07/2013 2:30am endTime 8/07/2013 4:30am. Case 2: Strt Time 8/07/2013 2:30am endTime 8/07/2013 4:30am another time interval Strt Time 8/07/2013 2:00am endTime 8/07/2013 4:00am. – surendher Jul 30 '13 at 06:01
  • refer http://stackoverflow.com/questions/10671468/check-if-the-time-and-date-is-between-a-particular-date-and-time?rq=1 – parilogic Jul 30 '13 at 09:55
  • 1
    if you want to check for "overlapping time intervals", then you should rename your question – AlexWien Jul 30 '13 at 10:06
  • 1
    Have a look at it might help : https://github.com/Chintan-Dave/CRDValidation – CRDave Jul 30 '13 at 10:49

4 Answers4

2

This code will give you what what you want. It checks if either the start date or end date of both intervals is between the start date and end date of the other interval.

- (BOOL)timeIntervalFromDate:(NSString *)dateString toDate:(NSString *)anotherDateString overlapsWithTimeIntervalFromDate:(NSString *)date2String toDate:(NSString *)anotherDate2String {
    BOOL isWithinRange = NO;

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"dd/MM/yyyy hh:mmaa";

    NSDate *date = [formatter dateFromString:dateString];
    NSDate *anotherDate = [formatter dateFromString:anotherDateString];
    NSDate *date2 = [formatter dateFromString:date2String];
    NSDate *anotherDate2 = [formatter dateFromString:anotherDate2String];

    NSDate *startDate = [date earlierDate:anotherDate];
    NSDate *endDate = [date laterDate:anotherDate];

    NSDate *otherStartDate = [date2 earlierDate:anotherDate2];
    NSDate *otherEndDate = [date2 laterDate:anotherDate2];

    BOOL startDateIsEarlierThanOtherStartDate = [startDate earlierDate:otherStartDate] == startDate;
    BOOL endDateIsLaterThanOtherStartDate = [endDate laterDate:otherStartDate] == endDate;

    BOOL startDateIsEarlierThanOtherEndDate = [startDate earlierDate:otherEndDate] == startDate;
    BOOL endDateIsLaterThanOtherEndDate = [endDate laterDate:otherEndDate] == endDate;

    BOOL otherStartDateIsEarlierThanStartDate = [startDate earlierDate:otherStartDate] == otherStartDate;
    BOOL otherEndDateIsLaterThanStartDate = [otherEndDate laterDate:startDate] == otherEndDate;

    BOOL otherEndDateIsEarlierThanStartDate = [startDate earlierDate:otherEndDate] == otherEndDate;
    BOOL otherEndDateIsLaterThanEndDate = [endDate laterDate:otherEndDate] == otherEndDate;

    isWithinRange = (startDateIsEarlierThanOtherStartDate && endDateIsLaterThanOtherStartDate) || (startDateIsEarlierThanOtherEndDate && endDateIsLaterThanOtherEndDate) || (otherStartDateIsEarlierThanStartDate && otherEndDateIsLaterThanStartDate) || (otherEndDateIsEarlierThanStartDate && otherEndDateIsLaterThanEndDate);

    return isWithinRange;
}

To account for each possible case, any of the pairs of boolean statements have to be true. It doesn't matter which order you supply the pairs of dates to the method.

Benjamin Mayo
  • 6,649
  • 2
  • 26
  • 25
  • By the way, I would recommend taking the `NSDateFormatter` code outside of this method, and instead having this method accepts `NSDate` objects directly. It is a better coding style, abstracting only what will not be repeated. – Benjamin Mayo Jul 30 '13 at 11:38
  • This can be expressed _far_ more simply. You only need to find which start date is earlier; then, if the corresponding end date is after the later start date, there is an overlap. This is three comparisons rather than eight. (See [my answer](http://stackoverflow.com/a/17955041/).) – jscs Jul 30 '13 at 18:59
1
-(BOOL)isDateInterval:(NSString*)startDate1 and:(NSString*)endDate1 fallsWithin:(NSString*)startDate2 and:(NSString*)endDate2
{
    BOOL isWithinrange;

    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];

    [formatter setDateFormat:@"dd/MM/yyyy hh:mmaa"];

    NSTimeInterval ti1 = [[formatter dateFromString:startDate2] timeIntervalSince1970];
    NSTimeInterval ti2 = [[formatter dateFromString:endDate2] timeIntervalSince1970];

    NSTimeInterval ti3 = [[formatter dateFromString:startDate1] timeIntervalSince1970];
    NSTimeInterval ti4 = [[formatter dateFromString:endDate1] timeIntervalSince1970];

    if( (ti3 > ti1 && ti3 < ti2) || (ti3 < ti1 && ti4 > ti1) )
    {
        //Date with in range
        isWithinrange=TRUE;
    }
    else
    {
        isWithinrange=FALSE;
        //Not with in range
    }

    return isWithinrange;
}
Apurv
  • 17,116
  • 8
  • 51
  • 67
  • @Apurv It will work only in one case, but always showing "Not With in Range" in following cases. Case 1:Strt Time 8/07/2013 2:00am endTime 8/07/2013 4:00am another interval Strt Time 8/07/2013 2:30am endTime 8/07/2013 4:30am. Case 2: Strt Time 8/07/2013 2:30am endTime 8/07/2013 4:30am another time interval Strt Time 8/07/2013 2:00am endTime 8/07/2013 4:00am. – surendher Jul 29 '13 at 15:06
  • @Apurv It should say "With in range" whenever the selected time interval falls in the another time interval – surendher Jul 29 '13 at 15:07
  • @surendher See the updated answer. It should check for proper range – Apurv Jul 30 '13 at 08:39
  • @surendher: You needed to change the start date and end date while calculating time intervals. Please see the updated answer. – Apurv Jul 30 '13 at 10:02
  • Still i am getting the Output "Not In Range". It should say "In range" if a part of the one time interval falls within other part of the interval. – surendher Jul 30 '13 at 10:09
  • Can you explain me the four input parameters of your function call.I mean which param decides range and which param decides whether they are in range. – Apurv Jul 30 '13 at 10:44
  • If interval Say A is 2-5 and B is 3-6. It should say within Range as we know 3-6 is taking some part in 2-5. Like this i want to check on date. Thanks for your continous support – surendher Jul 30 '13 at 10:48
  • I got it. But let me know, in the above function which dates are like 2-5 and which dates are like 3-6. I mean which dates define range and which dates need to check. – Apurv Jul 30 '13 at 10:51
  • It may be either Interval A or interval B, It can vary – surendher Jul 30 '13 at 11:32
1

We've got four dates, firstStartDate, firstEndDate, secondStartDate, and secondEndDate. Assuming that the two start dates are always actually earlier than their corresponding end dates, there are six ways these can be ordered:

+ start1 start2 end2 end1
+ start1 start2 end1 end2
x start1 end1 start2 end2
+ start2 start1 end2 end1
+ start2 start1 end1 end2
x start2 end2 start1 end1

Four of those orderings -- the ones I've marked with + -- constitute overlaps of the given time periods. The overlaps have this in common: whichever start date comes before the other, the matching end date must be after that second start. This is pretty easy to put into code:

@implementation NSDate (WSSComparisons)

- (BOOL)WSSIsLaterThanDate:(NSDate *)date
{
    return (self == [self laterDate:date]);
}

- (BOOL)WSSIsEarlierThanDate:(NSDate *)date
{
    return (self == [self earlierDate:date]);
}

@end

- (BOOL)periodFromDate:(NSDate *)firstStartDate toDate:(NSDate *)firstEndDate 
overlapsPeriodFromDate:(NSDate *)secondStartDate toDate:(NSDate *)secondEndDate
{
    /*
    // Sanity check?
    if( [firstStartDate WSSIsLaterThanDate:firstEndDate] || 
        [secondStartDate WSSIsLaterThanDate:secondEndDate] ){

        return NO;
    }
    */

    // If firstStartDate is before secondStartDate and firstEndDate isn't,
    // they overlap
    if( [firstStartDate WSSIsEarlierThanDate:secondStartDate] ){
        return [firstEndDate WSSIsLaterThanDate:secondStartDate];
    }
    else {
        // Likewise for secondStartDate
        return [secondEndDate WSSIsLaterThanDate:firstStartDate];
    }
}

If your "dates" happen to be strings, the logic is the same; just add an NSDateFormatter with the appropriate format and parse.

jscs
  • 63,694
  • 13
  • 151
  • 195
0

Take a look at the NSDate documentation from Apple.

Look at the methods:

isEqualToDate:, earlierDate:, laterDate:, and compare:

These are the methods you'll need to check if the dates are within a range. You'll need to convert your date text to an NSDate first. See the NSDateFormatter class reference.

Hopefully this gets you on the right path.

Baby Groot
  • 4,637
  • 39
  • 52
  • 71
stevekohls
  • 2,214
  • 23
  • 29