Formatting timedelta objects
But I was wondering if I can do it in a single line using any date time function like
strftime
.
As far as I can tell, there isn't a built-in method to timedelta
that does that. If you're doing it often, you can create your own function, e.g.
def strfdelta(tdelta, fmt):
d = {"days": tdelta.days}
d["hours"], rem = divmod(tdelta.seconds, 3600)
d["minutes"], d["seconds"] = divmod(rem, 60)
return fmt.format(**d)
Usage:
>>> print strfdelta(delta_obj, "{days} days {hours}:{minutes}:{seconds}")
1 days 20:18:12
>>> print strfdelta(delta_obj, "{hours} hours and {minutes} to go")
20 hours and 18 to go
If you want to use a string format closer to the one used by strftime
we can employ string.Template
:
from string import Template
class DeltaTemplate(Template):
delimiter = "%"
def strfdelta(tdelta, fmt):
d = {"D": tdelta.days}
d["H"], rem = divmod(tdelta.seconds, 3600)
d["M"], d["S"] = divmod(rem, 60)
t = DeltaTemplate(fmt)
return t.substitute(**d)
Usage:
>>> print strfdelta(delta_obj, "%D days %H:%M:%S")
1 days 20:18:12
>>> print strfdelta(delta_obj, "%H hours and %M to go")
20 hours and 18 to go
The
totalSeconds
value is shown as 13374 instead of 99774. I.e. it's ignoring the "day" value.
Note in the example above that you can use timedelta.days
to get the "day" value.
Alternatively, from Python 2.7 onwards, timedelta has a total_seconds() method which return the total number of seconds contained in the duration.
How to convert a python timedelta to a string that has a leading zero so it retains the format 00:00:00 (%HH:%MM:%SS)
It is a bit tricky, because the behaviour for negative values as well as values longer than a day is more complicated.
def str_td(td):
s = str(td).split(", ", 1)
a = s[-1]
if a[1] == ':':
a = "0" + a
s2 = s[:-1] + [a]
return ", ".join(s2)
print(str_td(datetime.timedelta(minutes=10)))
print(str_td(datetime.timedelta(minutes=3200)))
print(str_td(datetime.timedelta(minutes=-1400)))
print(str_td(datetime.timedelta(seconds=4003.2)))
print(str_td(datetime.timedelta(seconds=86401.1)))
gives
00:10:00
2 days, 05:20:00
-1 day, 00:40:00
01:06:43.200000
1 day, 00:00:01.100000
A completely different way of doing it would be
def str_td(td):
s = str(td).split(", ", 1)
t = datetime.time(td.seconds // 3600,td.seconds // 60 % 60,td.seconds % 60, td.microseconds)
s2 = s[:-1] + [str(t)]
return ", ".join(s2)
print(str_td(datetime.timedelta(minutes=10)))
print(str_td(datetime.timedelta(minutes=3200)))
print(str_td(datetime.timedelta(minutes=-1400)))
print(str_td(datetime.timedelta(seconds=4003.2)))
print(str_td(datetime.timedelta(seconds=86401.1)))
which gives the same result as above.
Which one is more elegant is left as an exercise to the reader.
Python format timedelta object to datetime
Don't use str(...)
, but use datetime.strftime
(the serializing counterpart to datetime.strptime
deserialization) with your original format string:
new_datetime = datetime_obj + timedelta(days=1)
print(new_datetime.strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
# 2020-11-16T00:00:00.000000Z
timedelta to string type in pandas dataframe
It is possible by:
df['duration1'] = df['duration'].astype(str).str[-18:-10]
But solution is not general, if input is 3 days 05:01:11
it remove 3 days
too.
So solution working only for timedeltas less as one day correctly.
More general solution is create custom format:
N = 10
np.random.seed(11230)
rng = pd.date_range('2017-04-03 15:30:00', periods=N, freq='13.5H')
df = pd.DataFrame({'duration': np.abs(np.random.choice(rng, size=N) -
np.random.choice(rng, size=N)) })
df['duration1'] = df['duration'].astype(str).str[-18:-10]
def f(x):
ts = x.total_seconds()
hours, remainder = divmod(ts, 3600)
minutes, seconds = divmod(remainder, 60)
return ('{}:{:02d}:{:02d}').format(int(hours), int(minutes), int(seconds))
df['duration2'] = df['duration'].apply(f)
print (df)
duration duration1 duration2
0 2 days 06:00:00 06:00:00 54:00:00
1 2 days 19:30:00 19:30:00 67:30:00
2 1 days 03:00:00 03:00:00 27:00:00
3 0 days 00:00:00 00:00:00 0:00:00
4 4 days 12:00:00 12:00:00 108:00:00
5 1 days 03:00:00 03:00:00 27:00:00
6 0 days 13:30:00 13:30:00 13:30:00
7 1 days 16:30:00 16:30:00 40:30:00
8 0 days 00:00:00 00:00:00 0:00:00
9 1 days 16:30:00 16:30:00 40:30:00
How to convert a string formatted timedelta back to int column in seconds
basically, you'd split the string on space to get the "days" part, split again on colon to get the H/M/S part. From there on it's just some simple math. Ex:
def tdstring_to_integerseconds(tdstr: str) -> int:
parts = tdstr.strip(' ').split(' ') # clean surrounding spaces and split
d = 0 # day default to zero...
if len(parts) > 1: # if more than one part, we have days specified
d = int(parts[0])
s = sum(x*y for x, y in zip(map(int, parts[-1].split(':')), (3600, 60, 1)))
return 86400*d + s
giving you for example
from datetime import timedelta
for td in timedelta(1), timedelta(-1), timedelta(0.5), timedelta(-1.5):
print(str(td), '->', tdstring_to_integerseconds(str(td)))
# 1 day, 0:00:00 -> 86400
# -1 day, 0:00:00 -> -86400
# 12:00:00 -> 43200
# -2 days, 12:00:00 -> -129600
How to make a proper Elapsed time? Python
You can use datetime.now
instead of time.time
and then convert it to timedelta
.
start = dt.datetime.now()
now = dt.datetime.now()
print(frmtdelta(now - start))
You need to write a function to compute hour
, minute
and second
. (We have days in timedelta
.)
import datetime as dt
import time
def frmtdelta(delta):
d = {"days": delta.days}
d["hr"], rem = divmod(delta.seconds, 3600)
d["min"], d["sec"] = divmod(rem, 60)
return "{days}d, {hr}h, {min}m, {sec}s".format(**d)
start = time.time()
while True:
now = time.time()
delta = dt.timedelta(seconds=int(now - start))
print(frmtdelta(delta))
time.sleep(.1)
Output:
0d, 0h, 0m, 0s
0d, 0h, 0m, 0s
0d, 0h, 0m, 0s
0d, 0h, 0m, 0s
0d, 0h, 0m, 0s
0d, 0h, 0m, 0s
0d, 0h, 0m, 0s
0d, 0h, 0m, 0s
0d, 0h, 0m, 0s
0d, 0h, 0m, 0s
0d, 0h, 0m, 1s
Format a negative timedelta as string with sign and hours, minutes, seconds
I can't seem to find the StackOverflow post where I found it, but there is a readabledelta module on github which you might find useful.
https://github.com/wimglenn/readabledelta
Related Topics
Python Dictionary Comprehension
How to Remove a Trailing Newline
Best Way to Convert String to Bytes in Python 3
Remove Specific Characters from a String in Python
What Does the Ellipsis Object Do
How to Connect to a MySQL Database in Python
How to Download Image Using Requests
Changing the "Tick Frequency" on X or Y Axis in Matplotlib
What Is Memoization and How to Use It in Python
How to Call a Script from Another Script
How to Merge Lists into a List of Tuples
How Does Assignment Work With List Slices