intrigued_66
intrigued_66

Reputation: 17258

Python convert string to datetime but formatting is not very predictable

I'm extract the execution time of a Linux process using Subprocess and ps. I'd like to put it in a datetime object, to perform datetime arithmetic. However, I'm a little concerned about the output ps returns for the execution time:

1-01:12:23    // 1 day, 1 hour, 12 minutes, 23 seconds   
  05:39:03    //        5 hours, 39 minutes, 3 seconds
     15:06    //                 15 minutes, 6 seconds

Notice there is no zero padding before the day. And it doesn't include months/years, whereas technically something could run for that long.

Consequently i'm unsure what format string to convert it to a timedelta because I don't want it to break if a process has ran for months, or another has only ran for hours.

UPDATE

Mozway has given a very smart answer. However, I'm taking a step back and wondering if I can get the execution time another way. I'm currently using ps to get the time, but it means I also have the pid. Is there something else I can do with the pid, to get the execution time in a simpler format?

(Can only use official Python libraries)

UPDATE2

It's actually colons between the hours, mins and seconds.

Upvotes: 1

Views: 122

Answers (1)

mozway
mozway

Reputation: 261015

You should use a timedelta

Here is a suggestion on how to convert from your string:

import datetime

s = '1-01-12-23'
out = datetime.timedelta(**dict(zip(['days', 'hours', 'minutes', 'seconds'],
                                map(int, s.split('-')))))

Output:

datetime.timedelta(days=1, seconds=4343)

If you can have more or less units, and assuming the smallest units are present you take advantage of the fact that zip stops with the smallest iterable, just reverse the inputs:

s = '12-23'
units = ['days', 'hours', 'minutes', 'seconds']

out = datetime.timedelta(**dict(zip(reversed(units),
                                map(int, reversed(s.split('-'))))))

Output:

datetime.timedelta(seconds=743)

As a function

Using re.split to handle the 1-01:23:45 format

import re

def to_timedelta(s):
    units = ['days', 'hours', 'minutes', 'seconds']
    return datetime.timedelta(**dict(zip(reversed(units),
                                         map(int, reversed(re.split('[-:]', s))))))

to_timedelta('1-01:12:23')
# datetime.timedelta(days=1, seconds=4343)

to_timedelta('05:39:03')
# datetime.timedelta(seconds=20343)

to_timedelta('15:06')
# datetime.timedelta(seconds=906)

Upvotes: 4

Related Questions