I want total number of hours between mention dates excluding weekend(Saturday, Sunday).
```
start_time = datetime.datetime(2021, 7, 1, 22, 45, 25)
end_time = datetime.datetime(2021, 7, 15, 10, 00, 00)
```
from BusinessHours import BusinessHours
import datetime
start_time = datetime.datetime(2021, 7, 1, 22, 45, 25)
end_time = datetime.datetime(2021, 7, 15, 10, 00, 00)
hours = BusinessHours(start_time, end_time, worktiming=[9, 18], weekends=[6, 7], holidayfile=None)
print(hours.gethours())
This could help you, for more information please refer BusinessHours module in python!
An additional library is needed for my answer (NumPy)
Key elements:
numpy.busday_count to count the number of weekdays
datetime.timedelta(1) to omit starting day (to be checked through if-else to count for minutes)
isoweekday() returns value between 1 and 7, 1 being Monday and 7 Sunday
Steps:
Skip the starting and ending days and find valid in-between days. Multiply by 24 (total hours per day)
Check if starting day is a weekday and calculate the total hours remaining to end that date
Check if the ending day is a weekday and calculate the total hours passed in that day
import datetime
import numpy as np
start_time = datetime.datetime(2021, 7, 1, 22, 45, 25)
end_time = datetime.datetime(2021, 7, 15, 10, 00, 00)
#Step 1.
total_hours=np.busday_count(start_time.date()+datetime.timedelta(1),end_time.date())*24 #already not counting last date
#Step2.
if start_time.isoweekday() in range(1, 6):
total_hours=total_hours+24-start_time.hour-start_time.minute/60-start_time.second/3600
#Step 3.
if end_time.isoweekday() in range(1, 6):
total_hours=total_hours+end_time.hour+end_time.minute/60+end_time.second/3600
print(total_hours)
output: 227.24305555555554
This will do it:
busdays = np.busday_count(start_time.date(), end_time.date())
Related
I have this code and I want to count the days between 2 dates.
from datetime import date, datetime
checkin= datetime(2022, 1, 30, 1, 15, 00)
checkout= datetime(2022, 1, 31, 0, 0, 00)
count_days= (checkout - checkin).days
In this case, the result of count_days result is 0, because in an operation with 2 datetimes, it takes into account hours, minutes and seconds.
I want the result to be 1 because is +1 day of difference. Type of variables must be datetimes. Thanks!
Convert them to dates first, with the date method.
from datetime import date, datetime
checkin = datetime(2022, 1, 30, 1, 15, 00)
checkout = datetime(2022, 1, 31, 0, 0, 00)
count_days = (checkout.date() - checkin.date()).days
Could you do something like this?
(assuming you want a minimum since the solution you have is similar)
from datetime import date, datetime
check_in= datetime(2022, 1, 30, 1, 15, 00)
check_out= datetime(2022, 1, 31, 0, 0, 00)
# Number of days between two dates (min 1 day)
days = (check_out - check_in).days + 1
print(days)
I have two UNIX timestamps that have distance in seconds D, where D = end - start. I want to find how many of these D seconds belong to an another time window [start2, end2], i.e. how many seconds intersect. Obviously it is not time2 - time1.
For example
start timestamp 1621707530 is Saturday, May 22, 2021 6:18:50 PM (GMT)
end timestamp 1621736330 is Sunday, May 23, 2021 2:18:50 AM (GMT)
How to find (preferably in Python) how many seconds between 01:00 AM and 02:00 AM belong to my [start, end] window?
For example interval [09:00 AM, 10:00 AM] does not intersect with [01:00 AM,02:00 AM], however interval [00:55 AM,01:03 AM] intersects for 3 minutes, or 180 seconds.
My code so far:
from datetime import datetime
from collections import namedtuple
Range = namedtuple('Range', ['start', 'end'])
r1 = Range(start=datetime(2021, 5, 22, 22, 23, 00),
end=datetime(2021, 5, 23, 2, 1, 2))
r2 = Range(start=datetime(2021, 5, 23, 1, 0, 00),
end=datetime(2021, 5, 23, 2, 0, 00))
latest_start = max(r1.start, r2.start)
earliest_end = min(r1.end, r2.end)
delta = (earliest_end - latest_start).seconds
overlap = max(0, delta)
print(overlap)
Can it be done with a simpler method?
Based on the answer: https://stackoverflow.com/a/46992092/14265469
The condition if (r1.start <= r2.end) and (r2.start <= r1.end): works surprisingly well:
from datetime import datetime
from collections import namedtuple
Range = namedtuple('Range', ['start', 'end'])
r1 = Range(start=datetime(2021, 5, 22, 22, 23, 20),
end=datetime(2021, 5, 22, 22, 23, 55))
r2 = Range(start=datetime(2021, 5, 22, 22, 23, 0),
end=datetime(2021, 5, 22, 22, 23, 25))
delta = "No overlapping"
if (r1.start <= r2.end) and (r2.start <= r1.end):
latest_start = max(r1.start, r2.start)
earliest_end = min(r1.end, r2.end)
delta = (earliest_end - latest_start).seconds
print(delta) # 5
hey guys i was trying to create a code that generate dates in given range but i faced some problems
the code is as follows:
import datetime
import random
import os
from random import randrange
year_b = 2019
month_b = 1
day_b = 1
year_e = 2020
month_e = 1
day_e = 1
def date_range(start, end, step: datetime.timedelta):
while start < end:
yield start
start += step
rand_list=[5,8,6,9,10]
for d in date_range(
start=datetime.datetime(year_b, month_b, day_b),
end=datetime.datetime(year_e, month_e, day_e),
step=datetime.timedelta(days=rand.choice(rand_list)),
):
print(d)
os.system("pause")
output:
2019-01-01 00:00:00
2019-01-09 00:00:00
2019-01-17 00:00:00
2019-01-25 00:00:00
2019-02-02 00:00:00
Press any key to continue . . .
first problem that the code only select one random value from the list and add it to the date but i need it to select random value for each date generated
second problem is that code the time it not been generated randomly
any ideas to solve those problems???!!
"Random" is often poorly defined. Why not select a specific number of samples uniformly from the distribution?
from datetime import datetime, timedelta
def items(start, end, samples):
total_sec = int((end - start).total_seconds())
deltas = random.sample(range(total_sec), samples) # xrange if py2k!
return (start + timedelta(seconds=delta) for delta in sorted(deltas))
Then you have
samples = 10
start = datetime(2019, 1, 1)
end = datetime(2020, 1, 1)
print(list(items(start, end, samples)))
giving, e.g.:
[datetime.datetime(2019, 1, 12, 16, 40, 53),
datetime.datetime(2019, 2, 1, 1, 41, 45),
datetime.datetime(2019, 2, 25, 10, 29, 51),
datetime.datetime(2019, 3, 10, 10, 24, 48),
datetime.datetime(2019, 4, 3, 12, 46, 14),
datetime.datetime(2019, 8, 12, 18, 30, 57),
datetime.datetime(2019, 9, 11, 3, 59, 6),
datetime.datetime(2019, 9, 27, 3, 9, 36),
datetime.datetime(2019, 10, 13, 14, 23, 37),
datetime.datetime(2019, 12, 14, 12, 23, 5)]
From this base you can easily modify to various other distributions, or use days or microseconds, or allow duplicates.
After reading your question more closely, I'm not entirely convinced this answer is what you're looking for, but I'll leave it up in case it is helpful.
The problem is because randrange(10) evaluates as soon as it is called. You can instead make date_range take a callable that returns a "random" time delta (or a variable delta, or whatever you'd like).
def adjustable_date_range(start, end, random_delta_maker):
while start < end:
yield start
start += random_delta_maker
And use it like so in your example by passing a callable that makes a random time delta on [0-10) days:
for d in adjustable_date_range(
start=datetime.datetime(year_b, month_b, day_b),
end=datetime.datetime(year_e, month_e, day_e),
step=lambda: datetime.timedelta(days=randrange(10)),
):
print(d)
now not all the months are showing:
from datetime import datetime, timedelta
import random
samples = 10
start = datetime(2018, 1, 1)
end = datetime(2020, 1, 1)
def items(start, end, samples):
total_sec = int((end - start).total_seconds())
deltas = random.sample(range(total_sec), samples) # xrange if py2k!
return (start + timedelta(seconds=delta) for delta in sorted(deltas))
for _ in list(items(start, end, samples)):
print(_)
output:
2018-02-01 18:25:48
2018-02-20 20:24:23
2018-06-07 22:03:48
2018-07-20 07:15:37
2018-08-22 07:04:06
2018-08-28 18:02:07
2018-10-09 03:40:58
2019-01-04 15:11:40
2019-03-22 12:16:58
2019-07-22 14:44:00
I have some trouble to understand the behavior of dateutil.relativedelta.
I understand that relativedelta could return past dates if I use negative arguments as specified in relativedelta doc.
However, when I provide positive parameters, I expect that it always return a date in the future... that seems legit right?
My use case is the following : we are Tuesday, it is 8:35. I want to get the date of the closest Monday and Tuesday at 6:00.
Here what I did. The first result seems correct to me, while the second one is wrong.
>>> import datetime
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2016, 11, 29, 8, 35, 23, 786349)
>>> from dateutil import relativedelta
>>> now.weekday()
1
>>> now + relativedelta.relativedelta(weekday=0, hour=6, minute=0) # should give a time in the future
datetime.datetime(2016, 12, 5, 6, 0, 23, 786349) # here this is correct, in the future
>>> now + relativedelta.relativedelta(weekday=1, hour=6, minute=0) # should give a time in the future
datetime.datetime(2016, 11, 29, 6, 0, 23, 786349) # but this is in the past / I would expect result (2016, 12, 6, 6, 0, 23, 786349)
So , am I doing something wrong here ?
So according to your initial date, you're actually at 8AM, but you're targeting 6AM by using the hour param, if you're trying to increment one hour, you should use hours and minutes respectively
>>> now
datetime.datetime(2016, 11, 29, 3, 5, 41, 763818)
>>> now.weekday()
1
>>> now + relativedelta.relativedelta(weekday=1, hour=1)
datetime.datetime(2016, 11, 29, 1, 5, 41, 763818) # Notice how it's in the past
>>> now + relativedelta.relativedelta(weekday=1, hours=1)
datetime.datetime(2016, 11, 29, 4, 5, 41, 763818) # Notice how it's one hour in the future
>>> n + relativedelta.relativedelta(weekday=1, hour=6, minute=0, weeks=1)
datetime.datetime(2016, 12, 6, 6, 0, 41, 763818)
I think it's in the doc:
Starting with, about weekday:
These instances may receive a parameter N, specifying the Nth weekday, which could be positive or negative (like MO(+1) or MO(-2). Not specifying it is the same as specifying +1.
So by passing 1, it's like you're passing (1, 1)
Then, continuing on the doc, on the 7th dot of behavior of operations with relativedelta:
Notice that if the calculated date is already Monday, for example, using (0, 1) or (0, -1) won’t change the day.
So the 29th of November is already a Tuesday, and you're asking for a Tuesday.
So nothing changes.
I am trying to output an altered time based on the "time" module in Py. For instance. I gather raw_input for the script from a user and based on that input I want to get system time and subtract a number of days from it and use that time for another step.
Thanks,
There are examples of all these steps here.
The datetime module is likely what you want.
Here is an example:
>>> from datetime import datetime, timedelta
>>> s = raw_input('Input year month day hour minute second: ')
Input year month day hour minute second: 2011 10 31 14 30 00
'2011 10 31 14 30 00'
>>> fields = map(int, s.split())
>>> fields
[2011, 10, 31, 14, 30, 0]
>>> userdate = datetime(*[2011, 10, 31, 14, 30, 0])
>>> userdate
datetime.datetime(2011, 10, 31, 14, 30)
>>> userdate - timedelta(days=20)
datetime.datetime(2011, 10, 11, 14, 30)
>>> now = datetime.now()
>>> now
datetime.datetime(2011, 10, 31, 11, 38, 34, 856511)
>>> now + timedelta(hours=2)
datetime.datetime(2011, 10, 31, 13, 38, 34, 856511)