Search code examples
pythondatetimepython-dateutil

How to convert a timedelta to a string and back again


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?


Solution

  • 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.