I want to get the total hours difference between two timestamps but I want to exclude certain hour in there . I want to count only these hours from 9AM-6PM everyday and other non working hours should be ignored.
I am ready to use panda as well if its not possible with python datetime module only.
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
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With