Last active
April 28, 2017 06:28
-
-
Save budidino/7fcabfc61f5f68d3ab30 to your computer and use it in GitHub Desktop.
handle foursquare hours API - return if venue is open, if it's going to be open or when it closed
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-(NSDictionary*)isVenueOpenDictionaryForHours:(NSArray*)hours{ | |
// defaults and inits | |
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; | |
NSDictionary *lastSegmentYesterday = [[NSDictionary alloc] init]; | |
NSDate *dateNow = [NSDate date]; | |
NSString *venueOpenText = [[NSString alloc] init]; | |
NSString *venueOpen = @"no"; | |
// get components for today | |
NSDateComponents *compsNow = [gregorian components:NSWeekdayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSDayCalendarUnit|NSMonthCalendarUnit|NSYearCalendarUnit fromDate:dateNow]; | |
// get weekday for today and yesterday so we can lookup 4sq API | |
NSInteger weekday = [compsNow weekday]; | |
NSInteger weekdayYesterday = (weekday>1)?weekday-1:7; | |
// look for todays' segment | |
NSMutableArray *venueOpenSegments = [[NSMutableArray alloc] init]; // stores all the segments when the venue is open | |
for (NSDictionary *segment in hours){ | |
// get today's segment (if it exists) | |
if ([segment[@"days"] containsObject:[NSNumber numberWithInteger:weekday]]){ | |
for (NSDictionary *dictOpen in segment[@"open"]) | |
[venueOpenSegments insertObject:@{@"end": [dictOpen[@"end"] mutableCopy], @"start":[dictOpen[@"start"] mutableCopy]}.mutableCopy atIndex:venueOpenSegments.count]; | |
} | |
// check the day before if the venue is open past midnight | |
if (([segment[@"days"] containsObject:[NSNumber numberWithInteger:weekdayYesterday]] && [segment[@"open"] count])){ | |
// get the last segment (that should be the one passing midnight) | |
NSDictionary *tempSegment = [segment[@"open"] lastObject]; | |
// if it has more than 4 characters it's after midnight ("+02:00"), also, ignore if it closes at midnight | |
if ([tempSegment[@"end"] length] > 4 && ![tempSegment[@"end"]isEqualToString:@"+0000"]){ | |
// create a new segment that starts at midnight and lasts till the time it closes (early AMs usually) | |
lastSegmentYesterday = @{@"start":@"0000", @"end":[tempSegment[@"end"] substringFromIndex:1]}; | |
} | |
} | |
} | |
// add last night segment that passes midnight as the first segment of today | |
if (lastSegmentYesterday.count){ | |
[venueOpenSegments insertObject:lastSegmentYesterday atIndex:0]; | |
} | |
// go through all the segments and find out if the venue is closed or open | |
if (venueOpenSegments.count){ | |
NSDateComponents *comps = [[NSDateComponents alloc] init]; | |
NSDateFormatter *timeFormatter = [[NSDateFormatter alloc]init]; | |
timeFormatter.dateFormat = @"HH:mm"; // set time output format | |
int segmentNumber = 0; | |
for (NSMutableDictionary *segment in venueOpenSegments){ | |
segmentNumber++; | |
// confing start date | |
[comps setDay:compsNow.day]; | |
[comps setMonth:compsNow.month]; | |
[comps setYear:compsNow.year]; | |
[comps setHour:[[segment[@"start"] substringToIndex:2] intValue]]; | |
[comps setMinute:[[segment[@"start"] substringFromIndex:2] intValue]]; | |
NSDate *dateStart = [[[NSCalendar currentCalendar] dateFromComponents:comps] copy]; | |
// config end date | |
// check if the segment goes to next day | |
BOOL closesTomorrow = NO; | |
if ( [segment[@"end"] length]==5 ){ | |
segment[@"end"] = [segment[@"end"] substringFromIndex:1]; | |
closesTomorrow = YES; | |
} | |
[comps setHour:[[segment[@"end"] substringToIndex:2] intValue]]; | |
[comps setMinute:[[segment[@"end"] substringFromIndex:2] intValue]]; | |
NSDate *dateEnd = [[[NSCalendar currentCalendar] dateFromComponents:comps] copy]; | |
// add a day if it closes tomorrow | |
if (closesTomorrow){ | |
NSDateComponents *nextDayComponent = [[NSDateComponents alloc] init]; | |
nextDayComponent.day = 1; | |
dateEnd = [gregorian dateByAddingComponents:nextDayComponent toDate:dateEnd options:0]; | |
} | |
// start checking if it's open or closed | |
// now < segment start | |
if ([dateNow compare:dateStart] == NSOrderedAscending){ | |
venueOpenText = [NSString stringWithFormat:@"opens at %@",[timeFormatter stringFromDate: dateStart]]; | |
venueOpen = @"later"; | |
break; | |
} | |
// segment end < now | |
else if ([dateEnd compare:dateNow] == NSOrderedAscending){ | |
if (segmentNumber == venueOpenSegments.count){ | |
venueOpenText = [NSString stringWithFormat:@"closed since %@",[timeFormatter stringFromDate: dateEnd]]; | |
break; | |
} | |
continue; | |
} | |
// segment start < now < segment end | |
else if ([dateStart compare:dateNow] == NSOrderedAscending && [dateNow compare:dateEnd] == NSOrderedAscending){ | |
venueOpenText = [NSString stringWithFormat:@"open till %@",[timeFormatter stringFromDate: dateEnd]]; | |
venueOpen = @"yes"; | |
break; | |
} | |
// rare but possible... last minute of the venue being open (I treat it as closed) | |
else { | |
venueOpenText = @"closing right now"; | |
} | |
} | |
} | |
else venueOpen = @"closed today"; // no segments for today, so it's closed for the dayæ | |
// return results | |
return @{@"open":venueOpen, @"string":venueOpenText}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Multiple methods named 'count' found with mismatched result, parameter type or attributes?