Format Timedelta to String

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



Leave a reply



Submit