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
I would like to measure the execution time of some piece of code in days, hours, minutes and seconds.
This is what I have so far:
import time
start_time = time.time()
# some code
elapsed = time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time))
print(f"Took: {elapsed}")
The problem is that if the code that I am measuring takes longer than 24h, the time displayed overflows and starts from zero again. I would like something like this:
# Example: 12 hours and 34 minutes should be printed as
> Took: 12:34:00
# Example: 26 hours and 3 minutes should be printed as
> Took: 1:02:03:00
You could use datetime:
from datetime import datetime as dt
start = dt.fromtimestamp(1588432670)
end = dt.now()
elapsed=end-start
print("Took: %02d:%02d:%02d:%02d" % (elapsed.days, elapsed.seconds // 3600, elapsed.seconds // 60 % 60, elapsed.seconds % 60))
Output:
Took: 33:00:21:49
The result of time.gmtime(time.time() - start_time) is not what you seem to think it is. Instead of being a duration of time it is a point in time. Let me explain.
The result of time.time() is the number of seconds since January 1, 1970, 00:00:00 (UTC) at the time of calling. Therefore, the statement time.time() - start_time will produce the number of seconds between the two calls. So far so good. However, the time.gmtime function is interpreting this duration as the number of seconds since January 1, 1970, 00:00:00 (UTC) and formatting the time accordingly. What you are seeing then is the time portion of the date January 1, 1970, 12:34:00 (UTC).
I suggest you either use the datetime.timedelta object and format using that, or as others have suggested, output the duration in seconds or milliseconds.
If you want to format this number yourself, you could use something like this:
def format_duration(duration):
mapping = [
('s', 60),
('m', 60),
('h', 24),
]
duration = int(duration)
result = []
for symbol, max_amount in mapping:
amount = duration % max_amount
result.append(f'{amount}{symbol}')
duration //= max_amount
if duration == 0:
break
if duration:
result.append(f'{duration}d')
return ' '.join(reversed(result))
You should try this:
import time
start_time = time.time()
...
elapsed_time = time.time() - start_time
days = 0
if elapsed_time >= 86400:
days = int(elapsed_time / 86400)
elapsed = time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time))
if days == 0:
print(f"Took: {elapsed}")
else:
print(f"Took: {days}:{eplased}")
Time types can only include hours and less units. You should use datetime instead of time as follows:
from datetime import datetime
start_time = datetime.now()
# some code
elapsed = datetime.now() - start_time)
print(f"Took: {elapsed}")
Example usage of Datetime:
from datetime import datetime
d1 = datetime(2013,9,1,5,5,4)
d2 = datetime(2013,1,13,3,2,1)
result1 = d1-d2
print ('{} between {} and {}'.format(result1, d1, d2))
This produces following output:
231 days, 2:03:03 between 2013-09-01 05:05:04 and 2013-01-13 03:02:01
Try using timeit:
import timeit
timeit.timeit(<callable function>, number = 100)
Here timeit will call callable function number times and give you the average runtime.
I expect that if I substract two datetimes in Python, I'll get datetime with substracted days, weeks, etc...
Here is my sample. What I get are just substracted hours, minutes and seconds. Date variable is taken from database. On type() function returns datetime.datetime.
def elapsed_time(date):
"""
Custom filter that format time to "x time age".
:param date:
:return:
"""
if date is None:
return 'No time given'
now = datetime.datetime.now()
elapsed = (now - date).seconds
if elapsed < 60:
return '{} seconds ago'.format(elapsed)
elif elapsed < 3600:
return '{} minutes ago'.format(int(elapsed / 60))
elif elapsed < 86400:
return '{} hours ago'.format(int(elapsed / 3600))
else:
return '{} days ago'.format((elapsed / 86400))
My current example:
Given datetime is 2017-07-27 01:18:58.398231
Current datetime is 2017-07-31 20:23:36.095440
Result is 19 hours (68677 seconds)
The following line returns only the 'seconds' component of the difference and does not take into account the days/hours/minutes components of it.
elapsed = (now - date).seconds
What you need is to use total_seconds() instead of just seconds since that's what you're trying to compare in subsequent conditions. Use it as follows:
elapsed = (now - date).total_seconds()
The rest of the code remains the same and you will get your desired output.
If you subtract two datetime objects the result will be a timedelta
import datetime as dt
import time
t1 = dt.datetime.now()
time.sleep(4)
t2 = dt.datetime.now()
dt1 = t2 - t1
print(dt1)
print(dt1.total_seconds())
print(type(dt1))
dt2 = t1 - t2
print(dt2.total_seconds())
print(dt2)
print(type(dt2))
If the second timestep was earlier than the first one, the results can be irritating. See negative day in example.
dt.seconds is only a part of the result, you are looking for
timedelta.total_seconds()
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
I have two times, a start and a stop time, in the format of 10:33:26 (HH:MM:SS). I need the difference between the two times. I've been looking through documentation for Python and searching online and I would imagine it would have something to do with the datetime and/or time modules. I can't get it to work properly and keep finding only how to do this when a date is involved.
Ultimately, I need to calculate the averages of multiple time durations. I got the time differences to work and I'm storing them in a list. I now need to calculate the average. I'm using regular expressions to parse out the original times and then doing the differences.
For the averaging, should I convert to seconds and then average?
Yes, definitely datetime is what you need here. Specifically, the datetime.strptime() method, which parses a string into a datetime object.
from datetime import datetime
s1 = '10:33:26'
s2 = '11:15:49' # for example
FMT = '%H:%M:%S'
tdelta = datetime.strptime(s2, FMT) - datetime.strptime(s1, FMT)
That gets you a timedelta object that contains the difference between the two times. You can do whatever you want with that, e.g. converting it to seconds or adding it to another datetime.
This will return a negative result if the end time is earlier than the start time, for example s1 = 12:00:00 and s2 = 05:00:00. If you want the code to assume the interval crosses midnight in this case (i.e. it should assume the end time is never earlier than the start time), you can add the following lines to the above code:
if tdelta.days < 0:
tdelta = timedelta(
days=0,
seconds=tdelta.seconds,
microseconds=tdelta.microseconds
)
(of course you need to include from datetime import timedelta somewhere). Thanks to J.F. Sebastian for pointing out this use case.
Try this -- it's efficient for timing short-term events. If something takes more than an hour, then the final display probably will want some friendly formatting.
import time
start = time.time()
time.sleep(10) # or do something more productive
done = time.time()
elapsed = done - start
print(elapsed)
The time difference is returned as the number of elapsed seconds.
Here's a solution that supports finding the difference even if the end time is less than the start time (over midnight interval) such as 23:55:00-00:25:00 (a half an hour duration):
#!/usr/bin/env python
from datetime import datetime, time as datetime_time, timedelta
def time_diff(start, end):
if isinstance(start, datetime_time): # convert to datetime
assert isinstance(end, datetime_time)
start, end = [datetime.combine(datetime.min, t) for t in [start, end]]
if start <= end: # e.g., 10:33:26-11:15:49
return end - start
else: # end < start e.g., 23:55:00-00:25:00
end += timedelta(1) # +day
assert end > start
return end - start
for time_range in ['10:33:26-11:15:49', '23:55:00-00:25:00']:
s, e = [datetime.strptime(t, '%H:%M:%S') for t in time_range.split('-')]
print(time_diff(s, e))
assert time_diff(s, e) == time_diff(s.time(), e.time())
Output
0:42:23
0:30:00
time_diff() returns a timedelta object that you can pass (as a part of the sequence) to a mean() function directly e.g.:
#!/usr/bin/env python
from datetime import timedelta
def mean(data, start=timedelta(0)):
"""Find arithmetic average."""
return sum(data, start) / len(data)
data = [timedelta(minutes=42, seconds=23), # 0:42:23
timedelta(minutes=30)] # 0:30:00
print(repr(mean(data)))
# -> datetime.timedelta(0, 2171, 500000) # days, seconds, microseconds
The mean() result is also timedelta() object that you can convert to seconds (td.total_seconds() method (since Python 2.7)), hours (td / timedelta(hours=1) (Python 3)), etc.
This site says to try:
import datetime as dt
start="09:35:23"
end="10:23:00"
start_dt = dt.datetime.strptime(start, '%H:%M:%S')
end_dt = dt.datetime.strptime(end, '%H:%M:%S')
diff = (end_dt - start_dt)
diff.seconds/60
This forum uses time.mktime()
Structure that represent time difference in Python is called timedelta. If you have start_time and end_time as datetime types you can calculate the difference using - operator like:
diff = end_time - start_time
you should do this before converting to particualr string format (eg. before start_time.strftime(...)). In case you have already string representation you need to convert it back to time/datetime by using strptime method.
I like how this guy does it — https://amalgjose.com/2015/02/19/python-code-for-calculating-the-difference-between-two-time-stamps.
Not sure if it has some cons.
But looks neat for me :)
from datetime import datetime
from dateutil.relativedelta import relativedelta
t_a = datetime.now()
t_b = datetime.now()
def diff(t_a, t_b):
t_diff = relativedelta(t_b, t_a) # later/end time comes first!
return '{h}h {m}m {s}s'.format(h=t_diff.hours, m=t_diff.minutes, s=t_diff.seconds)
Regarding to the question you still need to use datetime.strptime() as others said earlier.
Try this
import datetime
import time
start_time = datetime.datetime.now().time().strftime('%H:%M:%S')
time.sleep(5)
end_time = datetime.datetime.now().time().strftime('%H:%M:%S')
total_time=(datetime.datetime.strptime(end_time,'%H:%M:%S') - datetime.datetime.strptime(start_time,'%H:%M:%S'))
print total_time
OUTPUT :
0:00:05
import datetime as dt
from dateutil.relativedelta import relativedelta
start = "09:35:23"
end = "10:23:00"
start_dt = dt.datetime.strptime(start, "%H:%M:%S")
end_dt = dt.datetime.strptime(end, "%H:%M:%S")
timedelta_obj = relativedelta(start_dt, end_dt)
print(
timedelta_obj.years,
timedelta_obj.months,
timedelta_obj.days,
timedelta_obj.hours,
timedelta_obj.minutes,
timedelta_obj.seconds,
)
result:
0 0 0 0 -47 -37
Both time and datetime have a date component.
Normally if you are just dealing with the time part you'd supply a default date. If you are just interested in the difference and know that both times are on the same day then construct a datetime for each with the day set to today and subtract the start from the stop time to get the interval (timedelta).
Take a look at the datetime module and the timedelta objects. You should end up constructing a datetime object for the start and stop times, and when you subtract them, you get a timedelta.
you can use pendulum:
import pendulum
t1 = pendulum.parse("10:33:26")
t2 = pendulum.parse("10:43:36")
period = t2 - t1
print(period.seconds)
would output:
610
import datetime
day = int(input("day[1,2,3,..31]: "))
month = int(input("Month[1,2,3,...12]: "))
year = int(input("year[0~2020]: "))
start_date = datetime.date(year, month, day)
day = int(input("day[1,2,3,..31]: "))
month = int(input("Month[1,2,3,...12]: "))
year = int(input("year[0~2020]: "))
end_date = datetime.date(year, month, day)
time_difference = end_date - start_date
age = time_difference.days
print("Total days: " + str(age))
Concise if you are just interested in the time elapsed that is under 24 hours. You can format the output as needed in the return statement :
import datetime
def elapsed_interval(start,end):
elapsed = end - start
min,secs=divmod(elapsed.days * 86400 + elapsed.seconds, 60)
hour, minutes = divmod(min, 60)
return '%.2d:%.2d:%.2d' % (hour,minutes,secs)
if __name__ == '__main__':
time_start=datetime.datetime.now()
""" do your process """
time_end=datetime.datetime.now()
total_time=elapsed_interval(time_start,time_end)
Usually, you have more than one case to deal with and perhaps have it in a pd.DataFrame(data) format. Then:
import pandas as pd
df['duration'] = pd.to_datetime(df['stop time']) - pd.to_datetime(df['start time'])
gives you the time difference without any manual conversion.
Taken from Convert DataFrame column type from string to datetime.
If you are lazy and do not mind the overhead of pandas, then you could do this even for just one entry.
Here is the code if the string contains days also [-1 day 32:43:02]:
print(
(int(time.replace('-', '').split(' ')[0]) * 24) * 60
+ (int(time.split(' ')[-1].split(':')[0]) * 60)
+ int(time.split(' ')[-1].split(':')[1])
)