Subtracting a string converted into a datetime object - python

I have a piece of code, which takes inputs in 24 hour time such as 23:59, and prints how much time is left, so if it was 11:59 in the morning, it would return 12 hours.
I have been able to do this so far, but I cannot tell what is going wrong with this code right now:
from datetime import datetime
def timeuntil(t):
time = t
future = datetime.strptime(time, '%H:%M').replace(day = datetime.now().day, year = datetime.now().year, month = datetime.now().month)
timeleft = (future - datetime.now())
return timeleft
For your reference, print(timeuntil(22:00)) returned 15:55:01.996377 when I ran it at 8:43 PM.
Thanks for your help.

The issue does not seem reproducible on my machine, even when defining the datetime objects to the time you specified. However It could be to do with replace() on your datetime.
There is really no need for this, and I think you would be best to create a datetime object correctly. Below addresses the problem and works as you have intended.
def timeuntil(begin):
hour, minute = map(int, begin.split(':'))
now = datetime.now()
future = datetime(now.year, now.month, now.day, hour, minute)
return (future - now)
print(timeuntil("23:59"))
#7:35:06.022166
If you want to specify a different timezone to run this in, we can define our datetime.now() with a timezone, however we will need to strip this off to calculate future - now.
def timeuntil(begin):
hour, minute = map(int, begin.split(':'))
now = datetime.now(timezone('US/Pacific')).replace(tzinfo=None)
future = datetime(now.year, now.month, now.day, hour, minute)
return (future - now)

I believe you want the number of seconds until you reach the next day. I find this easier to follow with the time module and direct calculations.
import time
secs_in_day = 60*60*24
secs_time_left_local = secs_in_day - (time.time() - time.altzone) % secs_in_day
hours = int(secs_time_left_local // 3600)
minutes = int((secs_time_left_local % 3600) // 60)
seconds = int((secs_time_left_local % 3600) % 60)
print(f'{hours:02}:{minutes:02}:{seconds:02}')

Related

How to convert object datetime.time.now() to object datetime.timedelta()?

I'm using the datetime.time.now() for the current time, i.e. I want to perform an operation that counts in the totals of the hours (e.g. 1h:45min - 0h:50min). I cannot convert the current time to the datetime.timedelta object.
There is no datetime.time.now() — you must mean datetime.now() which returns a datetime instance which has a year, month, and day as well as the time of day. If you want a different time on the same day you can use its attributes to construct one.
If you subtract two datetimes the result is a timedelta.
You can also subtract an arbitrary timedelta from a datetime (resulting in another datetime).
Note that timedelta instances only have the attributes days, seconds, and microseconds, so if you want to know how long they are in hours and minutes, you have to manually calculate them.
Here's an example of doing all of these things.
from datetime import datetime, timedelta
now = datetime.now() # Current time.
# Construct a time on the same day.
sunrise = datetime(now.year, now.month, now.day, hour=6, minute=58)
if sunrise > now: # Future
delta = sunrise - now
when = 'will be in'
ago = ''
else: # Past
delta = now - sunrise
when = 'happened'
ago = 'ago'
days = delta.days
seconds = delta.seconds
hours = delta.seconds//3600
minutes = (delta.seconds//60) % 60
print(f'sunrise {when} {hours} hours {minutes} minutes {ago}')
print(f'30 minutes before sunrise today is {sunrise - timedelta(minutes=30)}')
I think I've found it; I wanted to compare the current time with the sunrise and sunset that Python itself retrieved.
I've done it this way now (so the next one can do it too)
import datetime as dt
DTN = dt.datetime.now()
H = int(DTN .strftime("%H"))
M = int(DTN .strftime("%M"))
S = int(DTN .strftime("%S"))
t1 = dt.timedelta(hours= H, minutes= M, seconds=S)
t2 = dt.timedelta(hours= 1, minutes= 0, seconds=0)
if t1 > t2:
timeCal = t1-t2 }
elif t1<t2:
timeCal = t2-t1
else:
timeCal = t1+t2
print(timeCal)
actual time = 20:00:00
result: 19:00:00

How to add times that has HH:MM:SS,XX format in python

My expertise lack when it comes to understanding this time format. I am guessing the ,XXX is XXX/1000 of a second?
Nevertheless I am trying to add a text files that contains time stamp like these and sum up the total.
Below is an example,
00:03:33,950
00:03:34,590
This is what I have so far but I'm not sure how to add up the last part
Hours = s.split(":")[0]
Minutes = s.split(":")[1]
Seconds = (s.split(":")[2]).split(",")[0]
Total_seconds = (Hours * 3600) + (Minutes * 60) + (Seconds)
Total_Time = str(datetime.timedelta(seconds=Total_seconds))
Reed this documentation about time.strftime() format
For example
from time import gmtime, strftime
strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
--'Thu, 28 Jun 2001 14:17:15 +0000'--
Actually, you're halfway there.
All you have to do is to to convert your strs into int and pass them as parameters to the appropriate timedelta keywords.
from datetime import timedelta
Hours = int(s.split(":")[0])
Minutes = int(s.split(":")[1])
Seconds = int((s.split(":")[2]).split(",")[0])
Milliseconds = int((s.split(":")[2]).split(",")[1])
duration = timedelta(hours=Hours, minutes=Minutes, seconds=Seconds, milliseconds=Milliseconds)
After adding all the durations you need, str() the final timedelta object.
>>> durations_1 = timedelta(hours=2,milliseconds=750)
>>> durations_2 = timedelta(milliseconds=251)
>>> durations_sum = durations_1 + durations_2
>>> str(durations_sum)
'2:00:01.001000'
>>> str(durations_sum).replace('.',',')
'2:00:01,001000'

Get number of seconds until the start of the next hour

I'm currently using a REST API that only allows 1000 queries per hour
Once the 1000 queries are used up, you then have to wait until the beginning of the next hour for the counter to be reset
My aim is to determine the number of seconds that I have to wait until the start of the next hour
I'm currently using the time.sleep method to put the script to sleep until the start of the next hour
I've put together a rather crude solution as follows using the datetime library (adding two minutes to be safe)
import datetime
# Determine the seconds until the next hour (add 2 minutes to be safe)
now = datetime.datetime.now()
next_hour = datetime.datetime(now.year, now.month, now.day, now.hour + 1, 2)
sleep_seconds = (next_hour - now).seconds
# Put the execution to sleep for a while
print("Sleeping for {0} minutes...".format(sleep_seconds // 60))
time.sleep(sleep_seconds)
This script does work but is unreliable when the next hour is the start of the next day.
datetime expects hour values between 0..23
If the
datetime.datetime.now() method returned 23 the method would fail
if you pass 24 to the datetime object
It would also be unreliable if the next day crossed into the next month or year as well.
Could someone suggest a better solution that would account for these wrap around issues?
Think datetime.timedelta will help you in this case. Something like this:
import datetime
delta = datetime.timedelta(hours=1)
now = datetime.datetime.now()
next_hour = (now + delta).replace(microsecond=0, second=0, minute=2)
wait_seconds = (next_hour - now).seconds
The replace should work to round you down to the next hour.

Python time format with three-digit hour

How can I parse the time 004:32:55 into a datetime object? This:
datetime.strptime("004:32:55", "%H:%M:%S")
doesn't work becaush %H expects two digits. Any way to add the third digit?
Three options :
s = "004:32:55"
from datetime import datetime
datetime.strptime(s[1:], "%H:%M:%S") # from second 0 to the end
datetime.strptime(s, "0%H:%M:%S") # add 0 in formatting
from dateutil import parser # use dateutil
parser.parse(s)
There are 24 hours in a day so you can divide and get the modulus to figure out how many days and hours are in the time, then subtract the days, this needs some tweaking will get you started.
s = "04:32:55"
s = s.split(":",1)
hours, days = divmod(int(s[0]),24)
new_time = "{}:{}".format(hours,s[1])
past = datetime.now() - timedelta(days=days)
final = "{} {}".format(past.date().isoformat(),new_time)
print datetime.strptime(final,"%Y-%m-%d %H:%M:%S")
I chose a more pragmatic approach in the end and converted the time stamp to seconds:
hours = (0 if time_string.split(":")[0] == "000" else int(time_string.split(":")[0].lstrip("0")) * 3600)
mins = (0 if time_string.split(":")[1] == "00" else int(time_string.split(":")[1].lstrip("0")) * 60)
secs = (0 if time_string.split(":")[2] == "00" else int(time_string.split(":")[2].lstrip("0")))
return hours + mins + secs
Converting back to hours, minutes, and seconds is easy with datetime.timedelta(seconds=123).
EDIT:
A better solution (thanks to Ben):
hours = int(time_string.split(":")[0]) * 3600
mins = int(time_string.split(":")[1]) * 60
secs = int(time_string.split(":")[2])
return hours + mins + secs

Python convert timedeltas into hours in string format

I have a timedelta object which is 3457 hours
timedelta(hours=3457)
I want to represent it in "HH:MM" format, which is "3457:00"
I do:
from datetime import datetime
hours = timedelta(hours=3457)
hours_string = time.strftime("%H:%M", time.gmtime(hours.seconds))
print hours_string
"01:00"
How can I get "3457:00"?
Please note that 3457:00 is a nonsensical format. The "hour-colon-minutes" format is used in dates and times, and the hour then can't reasonably be any higher than 23. A more reasonable format is: 3457h 0m.
You can get it like this:
from datetime import timedelta
delta = timedelta(hours=3457)
minutes, seconds = divmod(delta.seconds, 60)
hours, minutes = divmod(minutes, 60)
hours += delta.days * 24
print '%sh %sm' % (hours, minutes)
Of course, an easier way is this:
from datetime import timedelta
delta = timedelta(hours=3457)
print delta
But that will give you "144 days, 1:00:00", which is a sane format, but not what you want.
As the timedelta documentation notes, only days, seconds and microseconds are stored internally -- which means you'll have to manually convert them to the units you want (hours and minutes). Here's one way to do that:
from datetime import timedelta
d = timedelta(hours=3457, minutes=42)
wholehours, seconds = divmod(d.seconds, 60*60)
wholeminutes = seconds//60
deltahours = d.days*24 + wholehours
print('{:d}:{:02d}'.format(deltahours, wholeminutes))
# 3457:42
Here's a simpler alternative that produces the same result:
def deltatime_hours_mins(dt, sep=':'):
secs = int(dt.total_seconds())
return '{:d}{}{:02d}'.format(secs//3600, sep, secs//60 % 60)
print(deltatime_hours_mins(d))

Categories