<s> import datetime <EOL> __version__ = "<STR_LIT>" <EOL> class BusinessTime ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , business_hours = None , weekends = ( <NUM_LIT:5> , <NUM_LIT:6> ) , holidays = None ) : <EOL> if business_hours is None : <EOL> business_hours = ( datetime . time ( <NUM_LIT:9> ) , datetime . time ( <NUM_LIT> ) ) <EOL> self . business_hours = business_hours <EOL> self . weekends = weekends <EOL> self . holidays = holidays <EOL> if callable ( self . holidays ) or self . holidays is None : <EOL> self . _holidaysGeneratorStart = None <EOL> self . _holidaysGenerator = None <EOL> self . _holidays = [ ] <EOL> else : <EOL> self . _holidays = self . holidays <EOL> arbitrary_date = datetime . datetime ( <NUM_LIT> , <NUM_LIT:1> , <NUM_LIT> ) <EOL> start = datetime . datetime . combine ( arbitrary_date , business_hours [ <NUM_LIT:0> ] ) <EOL> end = datetime . datetime . combine ( arbitrary_date , business_hours [ <NUM_LIT:1> ] ) <EOL> self . open_hours = end - start <EOL> def isweekend ( self , dt ) : <EOL> return dt . weekday ( ) in self . weekends <EOL> def _ensure_holidays_span_datetime ( self , dt ) : <EOL> if callable ( self . holidays ) : <EOL> if self . _holidaysGeneratorStart is None or dt < self . _holidaysGeneratorStart : <EOL> self . _holidaysGeneratorStart = dt <EOL> self . _holidaysGenerator = self . holidays ( dt ) <EOL> while len ( self . _holidays ) == <NUM_LIT:0> or dt > self . _holidays [ - <NUM_LIT:1> ] : <EOL> self . _holidays . append ( next ( self . _holidaysGenerator ) ) <EOL> def isholiday ( self , dt ) : <EOL> if type ( dt ) == datetime . datetime : <EOL> dt = dt . date ( ) <EOL> self . _ensure_holidays_span_datetime ( dt ) <EOL> return dt in self . _holidays <EOL> def isbusinessday ( self , dt ) : <EOL> return not self . isweekend ( dt ) and not self . isholiday ( dt ) <EOL> def isduringbusinesshours ( self , dt ) : <EOL> return self . isbusinessday ( dt ) and self . business_hours [ <NUM_LIT:0> ] <= dt . time ( ) < self . business_hours [ <NUM_LIT:1> ] <EOL> def iterdays ( self , d1 , d2 ) : <EOL> """<STR_LIT>""" <EOL> curr = datetime . datetime . combine ( d1 , datetime . time ( ) ) <EOL> end = datetime . datetime . combine ( d2 , datetime . time ( ) ) <EOL> if d1 . date ( ) == d2 . date ( ) : <EOL> yield curr <EOL> return <EOL> while curr < end : <EOL> yield curr <EOL> curr = curr + datetime . timedelta ( days = <NUM_LIT:1> ) <EOL> def iterweekdays ( self , d1 , d2 ) : <EOL> """<STR_LIT>""" <EOL> for dt in self . iterdays ( d1 , d2 ) : <EOL> if not self . isweekend ( dt ) : <EOL> yield dt <EOL> def iterbusinessdays ( self , d1 , d2 ) : <EOL> """<STR_LIT>""" <EOL> assert d2 >= d1 <EOL> if d1 . date ( ) == d2 . date ( ) and d2 . time ( ) < self . business_hours [ <NUM_LIT:0> ] : <EOL> return <EOL> first = True <EOL> for dt in self . iterdays ( d1 , d2 ) : <EOL> if first and d1 . time ( ) > self . business_hours [ <NUM_LIT:1> ] : <EOL> first = False <EOL> continue <EOL> first = False <EOL> if not self . isweekend ( dt ) and not self . isholiday ( dt ) : <EOL> yield dt <EOL> def _build_spanning_datetimes ( self , d1 , d2 ) : <EOL> businessdays = list ( self . iterbusinessdays ( d1 , d2 ) ) <EOL> if len ( businessdays ) == <NUM_LIT:0> : <EOL> return businessdays <EOL> businessdays = [ datetime . datetime . combine ( d , self . business_hours [ <NUM_LIT:0> ] ) for d in businessdays ] <EOL> if d1 > businessdays [ <NUM_LIT:0> ] : <EOL> businessdays [ <NUM_LIT:0> ] = d1 <EOL> if self . isbusinessday ( d2 ) and d2 >= datetime . datetime . combine ( d2 , self . business_hours [ <NUM_LIT:0> ] ) : <EOL> businessdays . append ( datetime . datetime . combine ( d2 , self . business_hours [ <NUM_LIT:1> ] ) ) <EOL> if d2 < businessdays [ - <NUM_LIT:1> ] : <EOL> businessdays [ - <NUM_LIT:1> ] = datetime . datetime . combine ( businessdays [ - <NUM_LIT:1> ] , d2 . time ( ) ) <EOL> else : <EOL> if len ( businessdays ) == <NUM_LIT:1> : <EOL> businessdays . append ( datetime . datetime . combine ( businessdays [ <NUM_LIT:0> ] , self . business_hours [ <NUM_LIT:1> ] ) ) <EOL> else : <EOL> businessdays [ - <NUM_LIT:1> ] = datetime . datetime . combine ( businessdays [ - <NUM_LIT:1> ] , self . business_hours [ <NUM_LIT:1> ] ) <EOL> return businessdays <EOL> def businesstimedelta ( self , d1 , d2 ) : <EOL> """<STR_LIT>""" <EOL> businessdays = self . _build_spanning_datetimes ( d1 , d2 ) <EOL> time = datetime . timedelta ( ) <EOL> if len ( businessdays ) == <NUM_LIT:0> : <EOL> if self . isduringbusinesshours ( d2 ) : <EOL> time += d2 - datetime . datetime . combine ( d2 , self . business_hours [ <NUM_LIT:0> ] ) <EOL> else : <EOL> prev = None <EOL> current = None <EOL> count = <NUM_LIT:0> <EOL> for d in businessdays : <EOL> if current is None : <EOL> current = d <EOL> current = datetime . datetime . combine ( d , current . time ( ) ) <EOL> if prev is not None : <EOL> if prev . date ( ) != current . date ( ) : <EOL> time += datetime . timedelta ( days = <NUM_LIT:1> ) <EOL> if count == len ( businessdays ) - <NUM_LIT:1> : <EOL> if current > d : <EOL> time -= datetime . timedelta ( days = <NUM_LIT:1> ) <EOL> time += self . open_hours - ( current - d ) <EOL> else : <EOL> time += d - current <EOL> count += <NUM_LIT:1> <EOL> prev = current <EOL> return time </s>
