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)
Related
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 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 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.
I have datetime.now() objects, and I want to know how many hours will pass before a specific hour the next day
I've tried this:
now = datetime.now()
then = datetime.now() + timedelta(days=1)
then.hour = 12 # doesn't work
hours = then - now
But I don't know how can I specify the exact hour for then object
I don't understand that you need. But you can try this
then = datetime.now() + timedelta(days=1, hours=12)
or this
then = datetime.now() + timedelta(days=1)
then.replace(hour=12)
If you need get diff in hour you should use
hours = (then - now).seconds // 3600
The timedelta object will give you the total number of seconds between two times. The below will give you the number of whole hours between then and now.
now = datetime.datetime.now()
then = datetime.datetime.now() + datetime.timedelta(days=1)
delta = then - now
hours = delta.total_seconds // 3600
If the problem is that you cannot specify particular hour for an existing datetime object, you can construct a future datetime object explicitly using some attributes from now:
from datetime import datetime
now = datetime.now()
then = datetime(year=now.year, month=now.month, day=now.day+1, hour=19)
There has to be an easier way to do this. I have objects that want to be refreshed every so often, so I want to record when they were created, check against the current timestamp, and refresh as necessary.
datetime.datetime has proven to be difficult, and I don't want to dive into the ctime library. Is there anything easier for this sort of thing?
if you want to compute differences between two known dates, use total_seconds like this:
import datetime as dt
a = dt.datetime(2013,12,30,23,59,59)
b = dt.datetime(2013,12,31,23,59,59)
(b-a).total_seconds()
86400.0
#note that seconds doesn't give you what you want:
(b-a).seconds
0
import time
current = time.time()
...job...
end = time.time()
diff = end - current
would that work for you?
>>> from datetime import datetime
>>> a = datetime.now()
# wait a bit
>>> b = datetime.now()
>>> d = b - a # yields a timedelta object
>>> d.seconds
7
(7 will be whatever amount of time you waited a bit above)
I find datetime.datetime to be fairly useful, so if there's a complicated or awkward scenario that you've encountered, please let us know.
EDIT: Thanks to #WoLpH for pointing out that one is not always necessarily looking to refresh so frequently that the datetimes will be close together. By accounting for the days in the delta, you can handle longer timestamp discrepancies:
>>> a = datetime(2010, 12, 5)
>>> b = datetime(2010, 12, 7)
>>> d = b - a
>>> d.seconds
0
>>> d.days
2
>>> d.seconds + d.days * 86400
172800
We have function total_seconds() with Python 2.7
Please see below code for python 2.6
import datetime
import time
def diffdates(d1, d2):
#Date format: %Y-%m-%d %H:%M:%S
return (time.mktime(time.strptime(d2,"%Y-%m-%d %H:%M:%S")) -
time.mktime(time.strptime(d1, "%Y-%m-%d %H:%M:%S")))
d1 = datetime.now()
d2 = datetime.now() + timedelta(days=1)
diff = diffdates(d1, d2)
Here's the one that is working for me.
from datetime import datetime
date_format = "%H:%M:%S"
# You could also pass datetime.time object in this part and convert it to string.
time_start = str('09:00:00')
time_end = str('18:00:00')
# Then get the difference here.
diff = datetime.strptime(time_end, date_format) - datetime.strptime(time_start, date_format)
# Get the time in hours i.e. 9.60, 8.5
result = diff.seconds / 3600;
Hope this helps!
Another approach is to use timestamp values:
end_time.timestamp() - start_time.timestamp()
By reading the source code, I came to a conclusion: the time difference cannot be obtained by .seconds:
#property
def seconds(self):
"""seconds"""
return self._seconds
# in the `__new__`, you can find the `seconds` is modulo by the total number of seconds in a day
def __new__(cls, days=0, seconds=0, microseconds=0,
milliseconds=0, minutes=0, hours=0, weeks=0):
seconds += minutes*60 + hours*3600
# ...
if isinstance(microseconds, float):
microseconds = round(microseconds + usdouble)
seconds, microseconds = divmod(microseconds, 1000000)
# ! 👇
days, seconds = divmod(seconds, 24*3600)
d += days
s += seconds
else:
microseconds = int(microseconds)
seconds, microseconds = divmod(microseconds, 1000000)
# ! 👇
days, seconds = divmod(seconds, 24*3600)
d += days
s += seconds
microseconds = round(microseconds + usdouble)
# ...
total_seconds can get an accurate difference between the two times
def total_seconds(self):
"""Total seconds in the duration."""
return ((self.days * 86400 + self.seconds) * 10**6 +
self.microseconds) / 10**6
in conclusion:
from datetime import datetime
dt1 = datetime.now()
dt2 = datetime.now()
print((dt2 - dt1).total_seconds())