1

I need to convert the following strings into either datetimes or strings in a different format. My input looks like these examples:

196h 26m 13s
95h 19m
45m 28s

My desired string output would be (But my final goal is to convert these strings into datetime objects):

196:26:13
95:19:00
00:45:28

In Excel, it would be [h]:mm:ss.

Note: As you can see, hours can be higher than 24.

I have tried to parse this string with the time.strptime() method, but it doesn't work with hours higher than 24. I have a solution with regular expressions, but I want to know if there is a more straightforward way to do this. What is the best way to solve this?

3
  • 4
    Those aren't points in time; those are durations of time. Thus, datetime, date, and time are entirely the wrong types to use; the correct type is timedelta, which does not have a built-in string-parsing method. Commented Jan 26, 2017 at 21:50
  • 1
    I would go the re way too Commented Jan 26, 2017 at 21:57
  • Thanks guys for the help! I would stay by the good old regex way Commented Jan 26, 2017 at 21:58

2 Answers 2

2

This would give you time deltas:

from datetime import timedelta

def to_timedelta(time_string):
    units = {'h': 'hours', 'd': 'days', 'm': 'minutes', 's': 'seconds'}
    return timedelta(**{units[x[-1]]: int(x[:-1]) for x in time_string.split()})

Test:

times = ['196h 26m 13s', '95h 19m', '45m 28s']
for t in times:
    print(to_timedelta(t))

Output:

8 days, 4:26:13
3 days, 23:19:00
0:45:28

timedelta takes these arguments;

datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

Using this mapping:

units = {'h': 'hours', 'd': 'days', 'm': 'minutes', 's': 'seconds'}

allows the short units in the string to be mapped to the corresponding names of the arguments. Using Pythons ** syntax, the resulting dictionary can be used as single argument that will be converted in to the matching keyword arguments.

Sign up to request clarification or add additional context in comments.

Comments

1

The first thing we should do is use a regular expression and use timedelta instead of datetime.

import datetime
import re

regex = re.compile(r'((?P<hours>\d+?)h)?((?P<minutes>\d+?)m)?((?P<seconds>\d+?)s)?')

def parse_time(time_str):
    parts = regex.match(time_str)
    if not parts:
        return
    parts = parts.groupdict()
    time_params = {}
    for (name, param) in parts.items():
        if param:
            time_params[name] = int(param)
    return datetime.timedelta(**time_params)


L = ["196h 26m 13s", "95h 19m", "45m 28s"]

for l in L:
    print(parse_time(l))

Output:

8 days, 4:00:00
3 days, 23:00:00
0:45:00

1 Comment

Thanks! I had a very similar solution based on regex

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.