11

Dateutil's timedelta object appears to have a custom __str__ method:

In [1]: from datetime import timedelta

In [2]: td = timedelta(hours=2)

In [3]: str(td)
Out[3]: '2:00:00'

What I'd like to do is re-create a timedelta object from its string representation. As far as I can tell, however, the datetime.parser.parse method will always return a datetime.datetime object (cf. https://dateutil.readthedocs.io/en/stable/parser.html):

In [4]: import dateutil.parser

In [5]: dateutil.parser.parse(str(td))
Out[5]: datetime.datetime(2016, 11, 25, 2, 0)

The only way I see now to do this is to, in the parlance of Convert a timedelta to days, hours and minutes, 'bust out some nauseatingly simple (but verbose) mathematics' to obtain the seconds, minutes, hours, etc., and pass these back to the __init__ of a new timedelta. Or is there perhaps a simpler way?

Community
  • 1
  • 1
Kurt Peek
  • 52,165
  • 91
  • 301
  • 526

3 Answers3

7

Use datetime.strptime to convert a string to timedelta.

import datetime

td = datetime.timedelta(hours=2)

# timedelta to string
s = str(td) # 2:00:00

# string to timedelta
t = datetime.datetime.strptime(s,"%H:%M:%S")
td2 = datetime.timedelta(hours=t.hour, minutes=t.minute, seconds=t.second)
SparkAndShine
  • 17,001
  • 22
  • 90
  • 134
  • 1
    From the source code for `datetime` (which appears to be available at https://svn.python.org/projects/sandbox/trunk/datetime/datetime.py), it would appear from the `__str__` method definition that there are some special changes if the `timedelta` includes days or microseconds. It looks like Will Roberts, the author of [pytimeparse](https://pypi.python.org/pypi/pytimeparse/1.1.5), has (painstakingly) covered all these cases. – Kurt Peek Nov 25 '16 at 16:00
4

The module pytimeparse, which was inspired by How to construct a timedelta object from a simple string, seems to do the heavy lifting by returning the number of seconds. I just put a wrapper around it which returns a timedelta object with the same number of seconds:

#!/usr/bin/env python3.5
import datetime
import pytimeparse
import unittest

def reconstruct_timedelta(td_string):
    seconds = pytimeparse.parse(td_string)
    return datetime.timedelta(seconds=seconds)

class TestReconstruction(unittest.TestCase):
    def test_reconstruct_timedelta_is_inverse_of_str(self):
        td = datetime.timedelta(weeks=300, days=20, hours=3, minutes=4, milliseconds=254, microseconds=984)
        td_reconstructed = reconstruct_timedelta(str(td))
        self.assertTrue(td == td_reconstructed)

if __name__ == "__main__":
    unittest.main()

As you can see from the test, the reconstructed timedelta object is the same as the original one, even when it is initialized with an arbitrary number if milliseconds and microseconds.

Community
  • 1
  • 1
Kurt Peek
  • 52,165
  • 91
  • 301
  • 526
0

How about use pickle? You may refer to https://docs.python.org/2/library/pickle.html Serialize the time delta object, and get back the object later.

import pickle 

tdi = pickle.dumps(td)

tdo = pickle.loads(tdi) # will have the time delta object 

str(tdo) 
kkiat
  • 541
  • 3
  • 11
  • Thanks, but I'd prefer to have the representation as a human-readable string rather than a sequence of bytes. – Kurt Peek Nov 25 '16 at 15:37