Looking for easiest way to calculate the difference between 2 python times and display the millisecond delta
I have 2 times
startTime = datetime.datetime.now().time()
do some stuff...
endTime= datetime.datetime.now().time()
This works fine and when I log the times out and I get something like this in my logs...
RequestStartTime = 08:56:19.188999
ResponseTime = 08:56:19.905999
When I try to simply subtract them like this
delta = endTime - startTime
I get the following error
unsupported operand type(s) for -: 'time' and 'time'
All I want to do is show the difference in microseconds and I can't figure it out
I want to show is 717000 ms
If you just use the result of now(), and don't convert them to times, you can take the difference & extract the bits you want in the form you want; for example:
startTime = datetime.datetime.now()
endTime= datetime.datetime.now()
delta = endTime - startTime
print str(delta).split(":")[2]
Try this:
from datetime import datetime, date
datetime.combine(date.today(), endTime) - datetime.combine(date.today(), startTime)
Hope this Helps.
To measure the difference manually, you should use time.monotonic() instead.
If you don't care about leap seconds (~1s error once per year and a half) and you need to display the local time:
#!/usr/bin/env python3
from datetime import datetime, timedelta, timezone
start = datetime.now(timezone.utc).astimezone() # current local time
# print("RequestStartTime = %s" % start.time())
end = datetime.now(timezone.utc).astimezone()
diff_milliseconds = (end - start) / timedelta(milliseconds=1)
print("%.0f ms" % diff_milliseconds)
The code works fine around/during DST transitions.
Note: it is different from the code that uses just .now(). If you use .now() (no argument) then you get a naive datetime object that represents local time and in that case if a DST transition happens between start and end times then end - start returns a completely wrong result i.e., the code may be wrong by an hour approximately couple of times per year in some timezones.
the reason why you are getting an error is because class time does not support subtraction. You must turn time into miliseconds (int format) to subtract from one another.
instead of using datetime, use time
import time
def timenow():
return int(round(time.time() * 1000))
startTime = timenow()
time.sleep(1)
endTime = timenow()
delta = endTime - startTime
print delta
The simplest solution would be to convert the datetime objects to timestamps and subtract those. If you use Python 3.3 or later you can simply do something along these lines
startTime = datetime.datetime.now(timezone.utc).timestamp()
...
endTime = datetime.datetime.now(timezone.utc).timestamp()
Then you can just subtract those.
In Python 2 you do not have the timestamp method available. One way around would be to use a timedelta object:
startTime = datetime.datetime.now(timezone.utc)
...
endTime = datetime.datetime.now(timezone.utc)
dt = (endTime - startTime).total_seconds()
A third option is to simply use raw timestamps with time.time() and subtract them to get the time interval in seconds and fraction of seconds.
To be extra safe you could use time.monotonic() as #Sebastian mentions.
This is the best answer for this problem:
https://stackoverflow.com/a/39651061/2686243
from datetime import datetime, date
duration = datetime.combine(date.min, end) - datetime.combine(date.min, beginning)
Related
How can I subtract end - start to get hours minutes and seconds of time completion in Python?
I have some pseudocode here, I want to convert the print statement to what I said above.
start = time.asctime(time.localtime(time.time()))
< some code here>
end = time.asctime(time.localtime(time.time()))
print(end - start)
a solution using datetime
You can use the datetime module in Python to subtract two datetime objects and obtain a timedelta object that represents the duration between the two times. The timedelta object can be further used to extract hours, minutes, and seconds by accessing its attributes total_seconds(), seconds, minutes, hours, and days. Here is an example:
import datetime
start = datetime.datetime.now()
end = datetime.datetime.now()
duration = end - start
hours, remainder = divmod(duration.total_seconds(), 3600)
minutes, seconds = divmod(remainder, 60)
This question already has answers here:
Format timedelta to string
(33 answers)
Closed 1 year ago.
How can I format this date.time variable to include on milliseconds up to 2dp?
Using the date.time module in Python, I have created 2 variables. These are as follows:
begin = datetime.datetime.now()
end = datetime.datetime.now()
I then print the variable below.
time_taken = end - begin
Printing this variable time_taken in this format 0:00:16.664335.
The question I want to ask, is there a simple way to round the milliseconds to 2dp?
I have searched other methods but they seem over-complicated and not worth using.
yes the simple way to round a variable:
{selected variable} = round({selected variable}, {number of dp})`
example:
time = 1.3454
time = round(time, 2)
print time
{out put is 1.35}
Hopes this helps.
Subtracting datetime objects return a timedelta object. It has time upto microseconds stored inside it.
You can get that value & round it to however many points of precision you require.
import time
from datetime import datetime
begin = datetime.now()
time.sleep(0.005) # 5 ms
end = datetime.now()
time_taken = end - begin # this is a timedelta object
time_taken_ms = round(time_taken.total_seconds() * 1000, 2)
print(time_taken_ms)
Output:
6.97
The result of subtracting two datetimes is a timedelta object which only stores days, seconds, and microseconds internally and that is what is normally displayed when you print their values. If you desire something different, you will need to define your own formatting function. Below is and example of one that does what you want with respect to milliseconds:
import datetime
import time
def format_timedelta(td):
""" Format a timedelta into this format D:H:M:SS.ss """
days = td.days
hours, remainder = divmod(td.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
seconds += td.microseconds / 1e6
return (f'{days}:{hours}:{minutes}:{seconds:02.2f}' if days else
f'{hours}:{minutes}:{seconds:02.2f}')
begin = datetime.datetime.now()
time.sleep(0.123) # 123 ms
end = datetime.datetime.now()
time_taken = end - begin
print(format_timedelta(time_taken)) # -> 0:0:0.12
I have two datetime.time values, exit and enter and I want to do something like:
duration = exit - enter
However, I get this error:
TypeError: unsupported operand type(s) for -: 'datetime.time' and
'datetime.time
How do I do this correctly? One possible solution is converting the time variables to datetime variables and then subtruct, but I'm sure you guys must have a better and cleaner way.
Try this:
from datetime import datetime, date
datetime.combine(date.today(), exit) - datetime.combine(date.today(), enter)
combine builds a datetime, that can be subtracted.
Use:
from datetime import datetime, date
duration = datetime.combine(date.min, end) - datetime.combine(date.min, beginning)
Using date.min is a bit more concise and works even at midnight.
This might not be the case with date.today() that might return unexpected results if the first call happens at 23:59:59 and the next one at 00:00:00.
instead of using time try timedelta:
from datetime import timedelta
t1 = timedelta(hours=7, minutes=36)
t2 = timedelta(hours=11, minutes=32)
t3 = timedelta(hours=13, minutes=7)
t4 = timedelta(hours=21, minutes=0)
arrival = t2 - t1
lunch = (t3 - t2 - timedelta(hours=1))
departure = t4 - t3
print(arrival, lunch, departure)
You have two datetime.time objects so for that you just create two timedelta using datetime.timedetla and then substract as you do right now using "-" operand. Following is the example way to substract two times without using datetime.
enter = datetime.time(hour=1) # Example enter time
exit = datetime.time(hour=2) # Example start time
enter_delta = datetime.timedelta(hours=enter.hour, minutes=enter.minute, seconds=enter.second)
exit_delta = datetime.timedelta(hours=exit.hour, minutes=exit.minute, seconds=exit.second)
difference_delta = exit_delta - enter_delta
difference_delta is your difference which you can use for your reasons.
The python timedelta library should do what you need. A timedelta is returned when you subtract two datetime instances.
import datetime
dt_started = datetime.datetime.utcnow()
# do some stuff
dt_ended = datetime.datetime.utcnow()
print((dt_ended - dt_started).total_seconds())
datetime.time can not do it - But you could use datetime.datetime.now()
start = datetime.datetime.now()
sleep(10)
end = datetime.datetime.now()
duration = end - start
datetime.time does not support this, because it's nigh meaningless to subtract times in this manner. Use a full datetime.datetime if you want to do this.
import datetime
def diff_times_in_seconds(t1, t2):
# caveat emptor - assumes t1 & t2 are python times, on the same day and t2 is after t1
h1, m1, s1 = t1.hour, t1.minute, t1.second
h2, m2, s2 = t2.hour, t2.minute, t2.second
t1_secs = s1 + 60 * (m1 + 60*h1)
t2_secs = s2 + 60 * (m2 + 60*h2)
return( t2_secs - t1_secs)
# using it
diff_times_in_seconds( datetime.datetime.strptime( "13:23:34", '%H:%M:%S').time(),datetime.datetime.strptime( "14:02:39", '%H:%M:%S').time())
timedelta accepts negative(-) time values. so it could be simple as below.
Answer (single line)
datetime.timedelta(hours=exit.hour-enter.hour, minutes=exit.minute-enter.minute)
Run test
import datetime
enter = datetime.time(hour=1, minute=30)
exit = datetime.time(hour=2, minute=0)
duration = datetime.timedelta(hours=exit.hour-enter.hour, minutes=exit.minute-enter.minute)
>>> duration
datetime.timedelta(seconds=1800)
I had similar situation as you and I ended up with using external library called arrow.
Here is what it looks like:
>>> import arrow
>>> enter = arrow.get('12:30:45', 'HH:mm:ss')
>>> exit = arrow.now()
>>> duration = exit - enter
>>> duration
datetime.timedelta(736225, 14377, 757451)
import time
from datetime import datetime
def calcTime(enter,exit):
format="%H:%M:%S"
#Parsing the time to str and taking only the hour,minute,second
#(without miliseconds)
enterStr = str(enter).split(".")[0]
exitStr = str(exit).split(".")[0]
#Creating enter and exit time objects from str in the format (H:M:S)
enterTime = datetime.strptime(enterStr, format)
exitTime = datetime.strptime(exitStr, format)
return exitTime - enterTime
enter = datetime.today().time()
#Sleeping for 5 seconds before initializing the exit variable
time.sleep(5)
exit = datetime.today().time()
duration = calcTime(enter,exit)
print(f"Duration is {duration} (Hours:Minutes:Seconds)")
#Output: Duration is 0:00:05 (Hours:Minutes:Seconds)
If it is helpful, you can use the calcTime function as shown.
I am trying to get get the time delta i minutes from two different time values.
time1 = 2020-11-28T10:31:12Z
time2 = 2020-11-28T09:10:23.203+0000
Then i will make i condition: if time difference is bigger then x minutes, run code...
Anyone have a solution for that.
I have tried using datetime.datetime.strptime() but cant get them on same format.
Thanks
Using date parser to let it figure out the date format
Code
from dateutil.parser import parse
def time_difference(time1, time2):
# Parse strings into datetime objects
dt1 = parse(time1)
dt2 = parse(time2)
# Get timedelta object
c = dt1 - dt2
# Difference in minutes
return (c.total_seconds()/60)
Test
time1 = "2020-11-28T10:31:12Z"
time2 = "2020-11-28T09:10:23.203+0000"
print(time_difference(time1, time2))
# Output: 80.81328333333333
well assuming you don't need split seconds you could do something like that:
time1 = '2020-11-28T10:31:12Z'
time2 = '2020-11-28T09:10:23.203+0000'
import time
import datetime
def get_timestamp(time_str):
time_splited = time_str.split('T')
time_str_formatted = ' '.join([time_splited[0],time_splited[1][:8]])
return time.mktime(datetime.datetime.strptime(time_str_formatted,"%Y-%m-%d %H:%M:%S").timetuple())
print(get_timestamp(time1))
print(get_timestamp(time2))
reformatting both times to the same time format.
then your condition would look like:
if abs(get_timestamp(time1) -get_timestamp(time2) ) > x*60:
do_something(....)
The times are not uniform so you will have to make them the same to use strptime. For accuracy I prefer to convert to seconds then you can also at a later stage compare seconds, minutes or hours if you needed to.
import datetime
time1 = '2020-11-28T10:31:12Z'
time2 = '2020-11-28T09:10:23.203+0000'
def minutes_diff():
#Make the times uniform so you can then use strptime
date_time1 = datetime.datetime.strptime(time1[:-1], "%Y-%m-%dT%H:%M:%S")
date_time2 = datetime.datetime.strptime(time2[:-9], "%Y-%m-%dT%H:%M:%S")
#Convert to seconds for accuracy
a_timedelta = date_time1 - datetime.datetime(1900, 1, 1)
b_timedelta = date_time2 - datetime.datetime(1900, 1, 1)
seconds_time_a = a_timedelta.total_seconds()
seconds_time_b = b_timedelta.total_seconds()
#Take one from each other for minutes
time_in_minutes = (seconds_time_a - seconds_time_b) / 60
#Then decide what to do with it
if time_in_minutes < 60: # 1 hour
print('Less than an hours do something')
else:
print('More than an hour do nothing')
minutes_diff()
DARRYL, JOHNNY and MARCIN, thanks for your solutions, problem solved!!
Andy
I have been thinking to do a sleep function where it sleeps until a certain date is called. My idea was based of date such as : 2019-01-20 12:00:00.
I haven't really figured out how to start to solve this problem. My idea was something similar such as
if there is a date given:
time.sleep(until the date and time)
So the question is how can I possibly be able to sleep until a certain time given in a value of 2019-01-20 12:00:00?
Easy, calculate how long it is, and sleep the time.
You can calculate how long it takes until your wakeup time is reached and sleep for the delta time.
Python can calculate with time intervals. If you subtract one timestamp from another, then you get a datetime.timedelta:
import datetime
import time
target = datetime.datetime(2019,1,20,12,0,0)
now = datetime.datetime.now()
delta = target - now
if delta > datetime.timedelta(0):
print('will sleep: %s' % delta)
time.sleep(delta.total_seconds())
print('just woke up')
of course, you can put that in a function:
import datetime
import time
target = datetime.datetime(2019,1,20,12,0,0)
def sleep_until(target):
now = datetime.datetime.now()
delta = target - now
if delta > datetime.timedelta(0):
time.sleep(delta.total_seconds())
return True
sleep_until(target)
You can check the return value: only if it slept, it returns True.
BTW: it's OK, to use a date in the past as target. This will generate a negative number of seconds. Sleeping a negative value will just not sleep.
if your time is a string, use this:
target = datetime.datetime.strptime('20.1.2019 20:00:00', '%d.%m.%Y %H:%M:%s')
or
target = datetime.datetime.strptime('2019-1-20 20:00:00', '%Y-%m-%d %H:%M:%s')
I did your problem in an efficient way:
import time, datetime
# given_date --> Your target time and date
dur = time.mktime(datetime.datetime.strptime(given_date, "%d-%b-%y %H:%M:%S").timetuple()) - time.time()
time.sleep(dur)
you mean something like this:
from time import sleep
from datetime import datetime
x = datetime.datetime.strptime('2019-01-20 12:00:00', '%Y-%m-%d %H:%M:%S')
y = datetime.now()
sleep((max(x,y) - min(x,y)).seconds)
You can use a while loop.
import datetime
_theday="01/01/2019"
while datetime.today() != _theday:
some stuff