I am trying to write a script that runs continuously in the background to countdown to a repeated weekly event. For example, it should tell me how many days, hours, and minutes it will take to reach the specified time.
I know how to do it if I had a specific date and time.
import datetime
delta = datetime.datetime(2018, 5, 5, 8) - datetime.datetime.now()
But what if I don't have a specific date and time? Can datetime let me choose the day of the week?
EDIT:
i.e. Some pseudocode like this is what I need.
delta = datetime(Thursday 8 PM) - datetime.datetime.now()
#returns datetime or timedelta in days, hours, minutes
EDIT:
Thanks Ethan, i appreciate your constructive advice.
I wrote a small script which should do what you want:
import datetime
import time
wanted_day = 'thursday'
wanted_time = 8
list = [['monday', 0],['tuesday', 1],['wednesday', 2],['thursday', 3],['friday', 4],['saturday', 5],['sunday', 6]]
for i in list:
if wanted_day == i[0]:
number_wanted_day = i[1]
# today delivers the actual day
today = datetime.datetime.today().weekday()
# delta_days describes how many days are left until the wanted day
delta_days = number_wanted_day - today
# time delivers the actual time
time = time.localtime(time.time())
if wanted_time > time[3]:
delta_hours = wanted_time - time[3]
delta_mins = 59 - time[4]
delta_secs = 59 - time[5]
else:
delta_days = delta_days - 1
delta_hours = 23 - time[3] + wanted_time
delta_mins = 59 - time[4]
delta_secs = 59 - time[5]
print [delta_days, delta_hours, delta_mins, delta_secs]
The output looks like this then:
[2, 21, 3, 49]
2 is the number of days, 21 the number of hours, 3 the number of mins and 49 the number of secs (I used thursday 8 am as wanted time).
You just need to input the time in the format 0-23, with am and pm you would need to adapt it a bit
Related
Example:
9:43 - 17:27 - how many hours and minutes elapsed between those times ?
Here is one approach to get the number of total minutes:
from datetime import datetime
s = '9:30 - 14:00 ; 14:30 - 16:30'
sum(((b-a).total_seconds()/60 for x in s.split(' ; ')
for a,b in [list(map(lambda t: datetime.strptime(t, '%H:%M'), x.split(' - ')))]))
Output: 390.0
If you know that the time periods will never span midnight, then you could simply split the time strings with time.split(":") and do the math yourself with the hours and minutes.
However, the correct solution would be to import the datetime module and calculate the timedelta.
This example could be condensed. I intentionally made it verbose without knowing exactly how you're getting your inputs:
from datetime import datetime
times = [
"9:30",
"14:00",
"14:30",
"16:30"
]
#Just using today's date to fill in the values with assumption all times are on the same day.
year = 2022
month = 6
day = 9
date_times = []
for time in times:
split_time = time.split(":")
hour = split_time[0]
minutes = split_time[1]
timestamp = datetime.datetime.today(year=year, month=month, day=day, hour=hour, min=minutes)
date_times.append(timestamp)
total_seconds = 0
for i in range(1, len(date_times), 2):
delta = date_times[i] - date_times[i-1] # The timedelta object returned will have days, seconds, milliseconds
total_seconds += delta.days * 86400 + delta.seconds
hours = total_seconds // 3600 # Integer division
minutes = round((total_seconds % 3600) / 60) # Change depending on if you want to round to nearest, or always up or down.
Is there any function, in python, that extracts time information from a string to get the time from the current local one?
For example:
I have a column with time information in the past compared to the current time (let's say UK time, approximately 20:00)
Time
10 hours # ago
6 hours # ago
12 hours # ago
2 days # ago
1 day # ago
I would like to have, looking at the current UK time, (i.e., approximately 20:00):
New_Time
10:00
14:00
8:00
48:00
24:00
The column above comes from the current local time minus the number of hours (from string to numerical) in Time column.
Is it something that I might do with a function? The New_Time is the output that I will need.
In case there might not be a function in python, my approach would be:
use something to detect the current time (to save it in a variable)
consider hours as 60 min and 1 day as 24 hours ... in order to run some mathematical operations, once transformed strings into numerical
subtract from the current time the amount of minutes/hours to go back in time
You can make use of the dateparser package (some explanation in comments):
import datetime
import dateparser # pip install dateparser
# a function to format timedelta to string needed below,
# see https://stackoverflow.com/q/538666/10197418
def timedelta2str(sec):
hours, remainder = divmod(sec, 3600)
return f'{int(hours):02}:{int(remainder//60):02}'
def formatTimeAgo(string, reftime):
# try to parser... if successful, you get a datetime object
dtobj = dateparser.parse(string, settings={'RELATIVE_BASE': reftime})
if isinstance(dtobj, datetime.datetime):
# calculate a timedelta object against reference time
td = reftime - dtobj
# now format output based on input (days or hours..)
if td >= datetime.timedelta(1):
return timedelta2str(td.total_seconds())
else:
return (reftime-td).strftime('%H:%M')
else:
return "N/A"
# exemplary input
t = ("10 hours", "6 hours", "2 days", "1 day")
# a reference time
reftime = datetime.datetime(2021,4,10,20)
for elem in t:
print(elem, '->', formatTimeAgo(elem, reftime))
# giving you
>>> 10 hours -> 10:00
>>> 6 hours -> 14:00
>>> 2 days -> 48:00
>>> 1 day -> 24:00
Now you can adjust that to be used on pandas.Series:
import pandas as pd
df = pd.DataFrame({'Time': ["10 hours", "6 hours", "12 hours", "2 days", "1 day"]})
df['New_Time'] = df['Time'].apply(formatTimeAgo, args=(reftime,))
df['New_Time']
0 10:00
1 14:00
2 08:00
3 48:00
4 24:00
Name: New_Time, dtype: object
You can create a method that would return the time that it was a few hours/days/... ago. For example, two methods that will respectively return what day it was x days ago and what hour it was x hours ago :
def getTimeDaysAgo(x):
today = datetime.datetime.now()
value = today.day - x
previousMonth = today.month - 1
previousMonthDuration = 30
if previousMonth == 2:
if today.year % 4 == 0:
previousMonthDuration = 29
else:
previousMonthDuration = 28
if previousMonth % 2 == 1:
previousMonthDuration = 31
return value if value >= 0 else value + previousMonthDuration
def getTimeHoursAgo(x):
value = datetime.datetime.now().hour - x
return value if value >= 0 else value + 24
I'm not sure why you want to get "48:00" as a result of 2 days ago and "10:00" as a result of 10 hours ago at the same time. Feel free to ask for more infos, I'd be glad to help you out.
I want to scale the current time in a range. Like my start time is 08:00 hours and end time is 19:00 hours which is a 11 hr period. scaled value of my start time should be 0 and scaled value of my end time should be 11. Times like 10:00 and 10:30 should be scaled as 1 and 1.5 respectively.My code
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%H:%M")
start_time = '08:00'
end_time = '19:00'
The above code is reading the variable as strings and I'm not able to perform calculations on them. Can some one help me achieving the scaling.
Thanks
Change now.strftime("%H:%M") to now.strftime("%H%M")
This way you can convert it to an integer, so you have 1000 instead of 10:00 and you can use addition and subtraction
You can extract hours and minutes from your time using datetime.hour and datetime.minute.
To get the scaled value you want, for the range you specified (08:00 to 19:00), you can have :
from datetime import datetime
now = datetime.now()
if(8 <= now.hour <= 19):
scaled_time = now.hour - 8
scaled_time += now.minute / 60
Hope it's help.
Edit: you can change 8 and 19 to variables that contain your start and end time, so you can easily modify them
You can divide timedelta objects obtained from subtracting two datetime objects.
>>> from datetime import datetime
>>> start = datetime(2019, 12, day=19, hour=8, minute=0)
>>> end = datetime(2019, 12, day=19, hour=19, minute=0)
>>> now = datetime.now()
>>> print((now - start) / (end - start))
0.7824158481565656
8 to 19 is exactly 11 hours, so you don't need to scale it just use current time minus to 8 o'clock. so problem is down to change string to hours in decimal.
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%H:%M")
start_time = '08:00'
end_time = '19:00'
def conv(s):
l = s.split(':')
h = int(l[0])
m = int(l[1])
return h+m/60
st = conv(start_time)
# et = conv(end_time)
n = conv(current_time)
scaled = n-st
print(scaled)
I have been trying some code for this, but I can't seem to completely wrap my head around it.
I have a set date, set_date which is just some random date as you'd expect and that one is just data I get.
Now I would like some error function that raises an error if datetime.now() is within 24 hours of the set_date.
I have been trying code with the timedelta(hours=24)
from datetime import datetime, timedelta
now = datetime.now()
if now < (set_date - timedelta(hours=24)):
raise ValidationError('')
I'm not sure whats right to do with this, what the good way to do is. How exactly do I check if the current time is 24 hours before the set date?
Like that?
if now-timedelta(hours=24) <= set_date <= now:
... #date less than 24 hours in the past
If you want to check for the date to be within 24 hours on either side:
if now-timedelta(hours=24) <= set_date <= now+timedelta(hours=24):
... #date within 24 hours
To check if the date is within 24 hours.
Take a difference between the current time and the past time and check if the no. of days is zero.
past_date = datetime(2018, 6, 6, 5, 27, 28, 369051)
difference = datetime.utcnow() - past_date
if difference.days == 0:
print "date is within 24 hours"
## Also you can check the difference between two dates in seconds
total_seconds = (difference.days * 24 * 60 * 60) + difference.seconds
# Edited. Also difference have in-built method which will return the elapsed seconds.
total_seconds = difference.total_seconds()
You can check if total_seconds is less than the desired time
It is as simple as that:
from datetime import datetime
#...some code...
if (datetime.now() - pastDate).days > 1:
print('24 hours have passed')
else:
print('Date is within 24 hours!')
What you do here is subtract the old date pastDate from the current date datetime.now(), which gives you a time delta datetime.timedelta(...) object. This object stores the number of days, seconds and microseconds which have passed since the old date.
That will do:
if now - timedelta(hours=24) <= set_date <= now + timedelta(hours=24):
#Do something
Which is equivalent to:
if now - timedelta(hours=24) <= set_date <= now or now <= set_date <= now + timedelta(hours=24):
# ---^--- in the past 24h ---^--- in the future 24h
#Do something
I am hoping to generate a range of timestamps between:
18:00 (EST) on October 6th, 2014
and the same time 400 seconds later with an interval size of 2.2 seconds.
Getting the start and end dates:
When I do the following:
start_time = datetime.datetime(year = 2014,
month = 10,
day = 6,
hour = 18,
tzinfo = pytz.timezone('US/Eastern'))
end_time = start_time + datetime.timedelta(seconds=400)
Something seems to fail:
start_time.isoformat() returns '2014-10-06T18:06:40-04:56'
end_time.isoformat() returns '2014-10-06T18:06:40-04:56'
note that the time-zone offset for both timestamps above are: -04:56 (4 hours and 56 minutes) even though EST is 5 hours behind UTC. ?
Getting the time range:
Moving forward, if I try to get a range of timestamps between these two dates every 2.2 seconds (i.e. 2200 ms):
ts = pd.date_range(start=start_time, end=end_time, freq='2200L')
I get:
> ts[0]
Timestamp('2014-10-06 18:56:00-0400', tz='US/Eastern', offset='2200L')
or in other words:
> ts[0].isoformat()
'2014-10-06T18:56:00-04:00'
which also does not make sense (note that the time is 18:56, even though I was asking to get a range between 18:00 and 18:06:40 (i.e. 400 seconds after 18:00)
I got tired of dealing with Python's awkward datetime implementation (particularly with respect to timezones), and have started using crsmithdev.com/arrow. A solution using this lib:
import arrow
start_time = arrow.get(2014, 10, 6, tzinfo='US/Eastern')
end_time = start_time.replace(seconds=400)
print start_time.isoformat()
print end_time.isoformat()
# alternate form
start_time = arrow.get('2014-10-06T18:00:00.000-04:00')
end_time = start_time.replace(seconds=400)
print start_time.isoformat()
print end_time.isoformat()
# get a datetime from an arrow object
start_time_dt = start_time.datetime
import dateutil.parser as parser
import datetime
start_time = parser.parse("06/Oct/2015 18:00 EST")
end_time = start_time + datetime.timedelta(seconds=400)
interval = datetime.timedelta(seconds=2.2)
current_time = start_time
while current_time < end_time:
current_time += interval
print current_time
but I probably dont understand what your issue is