I want to get the total hours difference between two timestamps but I want to exclude certain hour in there . I want to exclude these hours from 5PM-10AM everyday.
from datetime import datetime
def get_total_hours(model_instance):
datetime = model_instance.datetime
now = datetime.now()
diff = now - datetime
total_secs = diff.total_seconds()
hours = total_secs // 3600
return hours
CodePudding user response:
I'd envision the problem geometrically:
day n day n 1 etc...
_______________________________________________________________________
00:00 | | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
EXCLUDED| | | | | |-- t2 ---| |
| | | | | | | |
| | | | | | | |
| | | | | | | |
10:00 |.........|.........|.........|.........|.........|.........|.........|
| |xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| | |
| |xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| | |
| |xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| | |
COUNTED |-- t1 ---|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| | |
|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| | |
|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| | |
|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx|xxxxxxxxx| | |
17:00 |.........|.........|.........|.........|.........|.........|.........|
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
EXCLUDED| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
23:59 |_________|_________|_________|_________|_________|_________|_________|
Whatever t1 and t2 might be, your answer is the area of a rectangle (height x width) plus some edge case handling at the ends.
CodePudding user response:
First, check the remaining hours for each date.
Then, check the day gap between the start and end dates.
import datetime
dt_start = datetime.datetime(year=2022, month=7, day=31, hour=20)
dt_end = datetime.datetime(year=2022, month=8, day=2, hour=10, minute=30)
dt_start_gap_lb = dt_start.replace(hour=10, minute=0, second=0, microsecond=0)
dt_start_gap_ub = dt_start.replace(hour=17, minute=0, second=0, microsecond=0)
dt_end_gap_lb = dt_end.replace(hour=10, minute=0, second=0, microsecond=0)
dt_end_gap_ub = dt_end.replace(hour=17, minute=0, second=0, microsecond=0)
dt_start_remain = dt_start_gap_ub - max(dt_start_gap_lb, dt_start)
dt_end_remain = min(dt_end_gap_ub, dt_end) - dt_end_gap_lb
dt_start_remain_hours = 0 if dt_start_remain.days < 0 else dt_start_remain.seconds / 3600.0
dt_end_remain_hours = 0 if dt_end_remain.days < 0 else dt_end_remain.seconds / 3600.0
gap_hours = max((dt_end_gap_lb - dt_start_gap_ub).days * (17-10) dt_start_remain_hours dt_end_remain_hours, 0)
Results:
dt_start = datetime.datetime(year=2022, month=7, day=31, hour=20)
dt_end = datetime.datetime(year=2022, month=8, day=2, hour=10, minute=30)
> 7.5
dt_start = datetime.datetime(year=2022, month=7, day=31, hour=16, minute=30)
dt_end = datetime.datetime(year=2022, month=8, day=2, hour=10, minute=30)
> 8.0
dt_start = datetime.datetime(year=2022, month=7, day=31, hour=5, minute= 30)
dt_end = datetime.datetime(year=2022, month=7, day=31, hour=10, minute=30)
> 0.5
CodePudding user response:
Given a model Foo
with a field timestamp
, and t1
and t2
defined as per the question:
Foo.objects.filter(timestamp__gte=t1, timestamp__lte=t2
).exclude( timestamp__hour__gte=17 # up to 23 by definition
).exclude( timestamp__hour__lte=9 # down to 0 by definition
)
Alternatively,
.exclude( timestamp__hour__in=[
0,1,2,3,4,5,6,7,8,9,17,18,19,20,21,22,23 ])