I am using the awful library datetime and I trying to do what should be very easy. I have a collection of timestamps in my video file, and I want to simply subtract start_time from end_time and then take the sum of all and output, the total time of the video file. My data in my video file looks like this
<p begin="00:02:42.400" end="00:02:43.080" style="s2">product_1</p>
So my code,
start_time = dt.strptime(begin, '%H:%M:%S.%f')
endie_time = dt.strptime(end, '%H:%M:%S.%f')
diff += endie_time-start_time
What I am trying to do is to keep adding up 'diff'
I get this error,
UnboundLocalError: local variable 'diff' referenced before assignment
I think the error is because diff is a datetime object and it is not an integer. But then when I do `int(diff), nothing works.
How can I do this simple task? I appreciate any help I can get on this annoying problem.
Thanks
The fundamental issue here is that the datetime module deals with real-world wall clock times, whereas you're trying to deal with durations. The only really applicable class in the datetime module to deal with your problem appropriately is therefore timedelta, which essentially expresses durations. To parse your strings into a timedelta, you'll need to do so slightly manually:
>>> from datetime import timedelta
>>> h, m, s = '00:02:43.080'.split(':')
>>> timedelta(hours=int(h), minutes=int(m), seconds=float(s))
datetime.timedelta(seconds=163, microseconds=80000)
If you now have two such timedeltas, you can subtract them:
>>> end - start
datetime.timedelta(microseconds=680000)
And you can add them to an existing timedelta:
diff = timedelta()
diff += end - start
Complete example:
from datetime import timedelta
diff = timedelta()
def parse_ts(ts: str) -> timedelta:
h, m, s = ts.split(':')
return timedelta(hours=int(h), minutes=int(m), seconds=float(s))
timestamps = [('00:02:42.400', '00:02:43.080'), ...]
for start, end in timestamps:
diff += parse_ts(end) - parse_ts(start)
print(diff)
As the comments to the original question say, using
X += Y
requires that you have alredy defined X.
A possible fix would be:
import datetime as dt
diff = dt.timedelta(0) # Initialize the diff with 0
start_time = dt.datetime.strptime(begin, '%H:%M:%S.%f')
endie_time = dt.datetime.strptime(end, '%H:%M:%S.%f')
diff += endie_time-start_time # Accumulate the time difference in diff
Since it seems that you want to iterate over multiple star/end dates:
import datetime as dt
diff = dt.timedelta(0) # Initialize the diff with 0
for begin_i, end_i in zip(begin, end):
start_time = dt.datetime.strptime(begin_i, '%H:%M:%S.%f')
endie_time = dt.datetime.strptime(end_i , '%H:%M:%S.%f')
diff += endie_time-start_time # Accumulate the time difference in diff
In both cases above, diff will be of the dt.timedelta type.
Related
I have time variables that are currently strings:
Time
18:29:36.809889
18:30:16.291965
I want to compute the difference between those two values (perhaps as a floating point).
How do I parse the string and perform the operation?
Thanks!
This code will produce the difference in seconds
time1 = "18:29:36.809889"
time2 = "18:30:16.291965"
hr1, min1, sec1 = time1.split(":")
hr2, min2, sec2 = time2.split(":")
ms1 = float(sec1) + int(min1)*60 + int(hr1)*60*60
ms2 = float(sec2) + int(min2)*60 + int(hr2)*60*60
print(abs(ms2 - ms1))
I must add however, that computing time differences using string manipulation is not the right approach. Wherever you're getting the timestamps from, you could convert them to epoch time and get the difference much easier.
Convert time strings to datetime instances then take the difference which is a timedelta object from which you can get a floating-point value as the total number of seconds.
from datetime import datetime
a = '18:29:36.809889'
b = '18:30:16.291965'
date1 = datetime.strptime(a, '%H:%M:%S.%f')
date2 = datetime.strptime(b, '%H:%M:%S.%f')
delta = date2 - date1
print(delta)
print(delta.total_seconds(), "seconds")
Output:
0:00:39.482076
39.482076 seconds
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'm new to Python. After a couple days researching and trying things out, I've landed on a decent solution for creating a list of timestamps, for each hour, between two dates.
Example:
import datetime
from datetime import datetime, timedelta
timestamp_format = '%Y-%m-%dT%H:%M:%S%z'
earliest_ts_str = '2020-10-01T15:00:00Z'
earliest_ts_obj = datetime.strptime(earliest_ts_str, timestamp_format)
latest_ts_str = '2020-10-02T00:00:00Z'
latest_ts_obj = datetime.strptime(latest_ts_str, timestamp_format)
num_days = latest_ts_obj - earliest_ts_obj
num_hours = int(round(num_days.total_seconds() / 3600,0))
ts_raw = []
for ts in range(num_hours):
ts_raw.append(latest_ts_obj - timedelta(hours = ts + 1))
dates_formatted = [d.strftime('%Y-%m-%dT%H:%M:%SZ') for d in ts_raw]
# Need timestamps in ascending order
dates_formatted.reverse()
dates_formatted
Which results in:
['2020-10-01T00:00:00Z',
'2020-10-01T01:00:00Z',
'2020-10-01T02:00:00Z',
'2020-10-01T03:00:00Z',
'2020-10-01T04:00:00Z',
'2020-10-01T05:00:00Z',
'2020-10-01T06:00:00Z',
'2020-10-01T07:00:00Z',
'2020-10-01T08:00:00Z',
'2020-10-01T09:00:00Z',
'2020-10-01T10:00:00Z',
'2020-10-01T11:00:00Z',
'2020-10-01T12:00:00Z',
'2020-10-01T13:00:00Z',
'2020-10-01T14:00:00Z',
'2020-10-01T15:00:00Z',
'2020-10-01T16:00:00Z',
'2020-10-01T17:00:00Z',
'2020-10-01T18:00:00Z',
'2020-10-01T19:00:00Z',
'2020-10-01T20:00:00Z',
'2020-10-01T21:00:00Z',
'2020-10-01T22:00:00Z',
'2020-10-01T23:00:00Z']
Problem:
If I change earliest_ts_str to include minutes, say earliest_ts_str = '2020-10-01T19:45:00Z', the resulting list does not increment the minute intervals accordingly.
Results:
['2020-10-01T20:00:00Z',
'2020-10-01T21:00:00Z',
'2020-10-01T22:00:00Z',
'2020-10-01T23:00:00Z']
I need it to be:
['2020-10-01T20:45:00Z',
'2020-10-01T21:45:00Z',
'2020-10-01T22:45:00Z',
'2020-10-01T23:45:00Z']
Feels like the problem is in the num_days and num_hours calculation, but I can't see how to fix it.
Ideas?
if you don't mind to use a 3rd party package, have a look at pandas.date_range:
import pandas as pd
earliest, latest = '2020-10-01T15:45:00Z', '2020-10-02T00:00:00Z'
dti = pd.date_range(earliest, latest, freq='H') # just specify hourly frequency...
l = dti.strftime('%Y-%m-%dT%H:%M:%SZ').to_list()
print(l)
# ['2020-10-01T15:45:00Z', '2020-10-01T16:45:00Z', '2020-10-01T17:45:00Z', '2020-10-01T18:45:00Z', '2020-10-01T19:45:00Z', '2020-10-01T20:45:00Z', '2020-10-01T21:45:00Z', '2020-10-01T22:45:00Z', '2020-10-01T23:45:00Z']
import datetime
from datetime import datetime, timedelta
timestamp_format = '%Y-%m-%dT%H:%M:%S%z'
earliest_ts_str = '2020-10-01T00:00:00Z'
ts_obj = datetime.strptime(earliest_ts_str, timestamp_format)
latest_ts_str = '2020-10-02T00:00:00Z'
latest_ts_obj = datetime.strptime(latest_ts_str, timestamp_format)
ts_raw = []
while ts_obj <= latest_ts_obj:
ts_raw.append(ts_obj)
ts_obj += timedelta(hours=1)
dates_formatted = [d.strftime('%Y-%m-%dT%H:%M:%SZ') for d in ts_raw]
print(dates_formatted)
EDIT:
Here is example with Maya
import maya
earliest_ts_str = '2020-10-01T00:00:00Z'
latest_ts_str = '2020-10-02T00:00:00Z'
start = maya.MayaDT.from_iso8601(earliest_ts_str)
end = maya.MayaDT.from_iso8601(latest_ts_str)
# end is not included, so we add 1 second
my_range = maya.intervals(start=start, end=end.add(seconds=1), interval=60*60)
dates_formatted = [d.iso8601() for d in my_range]
print(dates_formatted)
Both output
['2020-10-01T00:00:00Z',
'2020-10-01T01:00:00Z',
... some left out ...
'2020-10-01T23:00:00Z',
'2020-10-02T00:00:00Z']
Just change
num_hours = num_days.days*24 + num_days.seconds//3600
The problem is that num_days only takes integer values, so if it is not a multiple of 24h you will get the floor value (i.e for your example you will get 0). So in order to compute the hours you need to use both, days and seconds.
Also, you can create the list directly in the right order, I am not sure if you are doing it like this for some reason.
ts_raw.append(earliest_ts_obj + timedelta(hours = ts + 1))
I want to be able to format a datetime object, while leaving it as an object. I have worked a way to do it, but it doesn't seem very efficient.
My specific aim is to limit the extra digits on the seconds to 2. This is how I am currently doing it:
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
now_frmt = datetime.datetime.strptime(now, '%Y-%m-%d %H:%M:%S')
Cheers,
JJ
You could do this to subtract off the microseconds:
now = datetime.datetime.now()
now_frmt = now - datetime.timedelta(microseconds=now.microsecond)
To round to the nearest second you can do the following:
now = datetime.datetime.now()
delta = (0 if now.microsecond < 500000 else 1000000) - now.microsecond
now_frmt = now + datetime.timedelta(microseconds=delta)
Datetime objects hurt my head for some reason. I am writing to figure out how to shift a date time object by 12 hours. I also need to know how to figure out if two date time object's differ by say 1 minute or more.
The datetime library has a timedelta object specifically for this kind of thing:
import datetime
mydatetime = datetime.now() # or whatever value you want
twelvelater = mydatetime + datetime.timedelta(hours=12)
twelveearlier = mydatetime - datetime.timedelta(hours=12)
difference = abs(some_datetime_A - some_datetime_B)
# difference is now a timedelta object
# there are a couple of ways to do this comparision:
if difference > timedelta(minutes=1):
print "Timestamps were more than a minute apart"
# or:
if difference.total_seconds() > 60:
print "Timestamps were more than a minute apart"
You'd use datetime.timedelta for something like this.
from datetime import timedelta
datetime arithmetic works kind of like normal arithmetic: you can add a timedelta object to a datetime object to shift its time:
dt = # some datetime object
dt_plus_12 = dt + timedelta(hours=12)
Also you can subtract two datetime objects to get a timedelta representing the difference between them:
dt2 = # some other datetime object
ONE_MINUTE = timedelta(minutes=1)
if abs(dt2 - dt) > ONE_MINUTE:
# do something