Вы можете использовать регулярное выражение для извлечения частей числа / времени, а затем искать множитель в словаре.Таким образом, он немного короче и, вероятно, намного более читабелен, чем ваш ручной анализ и if/elif
цепочка.
>>> mult = {"s": 1, "m": 60, "h": 60*60, "d": 60*60*24}
>>> s = "2d 4h 13m 5.2s"
>>> re.findall(r"(\d+(?:\.\d)?)([smhd])", s)
[('2', 'd'), ('4', 'h'), ('3', 'm'), ('5.2', 's')]
>>> sum(float(x) * mult[m] for x, m in _)
187385.2
Как функция:
def duration(string):
mult = {"s": 1, "m": 60, "h": 60*60, "d": 60*60*24}
parts = re.findall(r"(\d+(?:\.\d)?)([smhd])", string)
total_seconds = sum(float(x) * mult[m] for x, m in parts)
return timedelta(seconds=total_seconds)
print(duration("2d 4h 13m 5.2s"))
# 2 days, 4:03:05.200000
Это также гарантирует, что номерная часть является действительным числом (а не просто какой-либо последовательностью цифр и точек).Кроме того, это вызовет исключение, если используются какие-либо иные, чем разрешенные единицы времени.
Функция может быть дополнительно оптимизирована путем предварительной компиляции регулярного выражения с re.compile
вне функции.Когда я тестировал его с IPython %timeit
, мой показался немного быстрее (у вас 2,1 мкс против 2,8 мкс, как без создания timedelta
, так и с float
вместо Decimal
).Кроме того, я бы посчитал, что это будет более читабельным, если иметь гораздо более декларативный и менее императивный стиль, но это, безусловно, вопрос вкуса и предпочтений.