Я пишу функцию, которой требуется ввод timedelta в виде строки. Пользователь должен ввести что-то вроде "32m" или "2h32m", или даже "4:13" или "5hr34m56s" ... Есть ли библиотека или что-то подобное, что уже реализовано?
Для людей , просто глядя построить timedelta объект dдней, hчасов, mминут и sсекунд , используя одну строку (после импорта datetime): datetime.timedelta(days = d, hours = h, minutes=m, seconds=s).
zthomas.nc
Ответы:
72
Для первого формата (5hr34m56s) вы должны анализировать с помощью регулярных выражений
Вот новое решение:
import re
from datetime import timedelta
regex = re.compile(r'((?P<hours>\d+?)hr)?((?P<minutes>\d+?)m)?((?P<seconds>\d+?)s)?')def parse_time(time_str):
parts = regex.match(time_str)ifnot parts:return
parts = parts.groupdict()
time_params ={}for(name, param)in parts.iteritems():if param:
time_params[name]= int(param)return timedelta(**time_params)>>>from parse_time import parse_time
>>> parse_time('12hr')
datetime.timedelta(0,43200)>>> parse_time('12hr5m10s')
datetime.timedelta(0,43510)>>> parse_time('12hr10s')
datetime.timedelta(0,43210)>>> parse_time('10s')
datetime.timedelta(0,10)>>>
Я думал о какой-то функции, которая могла бы принять все, что вы ей бросили, и при этом иметь возможность обрабатывать преобразование в timedelta.
priestc
2
Я добавил пример решения на основе re :)
virhilo
4
Я не понимаю, как dateutil.parser.parse может анализировать продолжительность, похоже, что он всегда возвращает datetime. Что мне не хватает?
Николай
7
dateutil.parser.parseне будет анализировать timedeltaобъекты. Он возвращает a datetimeи вызывает исключение для таких строк, как '28:32:11.10'.
Spak
95
Для меня наиболее элегантным решением без использования внешних библиотек, таких как dateutil или ручного синтаксического анализа ввода, является использование мощного метода синтаксического анализа строк datetimestrptime .
from datetime import datetime, timedelta
# we specify the input and the format...
t = datetime.strptime("05:20:25","%H:%M:%S")# ...and use datetime's hour, min and sec properties to build a timedelta
delta = timedelta(hours=t.hour, minutes=t.minute, seconds=t.second)
После этого вы можете использовать свой объект timedelta как обычно, преобразовать его в секунды, чтобы убедиться, что мы все сделали правильно и т. Д.
Обратите внимание, что этот подход работает только в том случае, если временной интервал составляет менее 24 часов ( datetime.strptime("32:20:25","%H:%M:%S")не работает), и вы должны знать точный формат ввода.
Verdesmarald 02
Это также только часть ответа на вопрос ОП. Если функции необходимо иметь дело с несколькими форматами, вам все равно потребуется дополнительная проверка формата (1 двоеточие или 2?).
Дэнни Стейпл
3
@verdesmarald Итак, начиная с python 3.5, есть ли элегантное решение без использования внешних библиотек и без предположения, что временной интервал составляет менее 24 часов?
max
1
Я считаю, что необходимость вручную указывать именованные параметры для timedeltaпараметра довольно раздражает, но лучшее, что я могу придумать, чтобы избежать этого, - это:, delta = t - datetime.combine(t.date(), time.min)что ... ужасно.
Kyle Strand
2
Серьезная проблема с этим подходом заключается в том, что если вы включите дни, а затем отправите% d в strptime, вы не сможете ввести день 0, поскольку для даты действительны только дни> = 1.
user1581390
75
У меня было немного времени на моих руках вчера, поэтому я разработал @virhilo «s ответ в модуль Python, добавив несколько времени более форматов выражений, в том числе все те , по просьбе @priestc .
@ luca.giovagnoli В Scala вы можете использовать класс Duration. Продолжительность может быть построена из таких строк, как «15 секунд», «4 минуты» и т. Д.
Конрад Малик
14
Я хотел ввести только время, а затем добавить его к различным датам, чтобы у меня это сработало:
from datetime import datetime as dtt
time_only = dtt.strptime('15:30',"%H:%M")- dtt.strptime("00:00","%H:%M")
добавлено утверждение, что строка является допустимой строкой времени
замените часовой индикатор "hr" на "h"
включить индикатор "d" дней
разрешить нецелое время (например 3m0.25s, 3 минуты 0,25 секунды)
.
import re
from datetime import timedelta
regex = re.compile(r'^((?P<days>[\.\d]+?)d)?((?P<hours>[\.\d]+?)h)?((?P<minutes>[\.\d]+?)m)?((?P<seconds>[\.\d]+?)s)?$')def parse_time(time_str):"""
Parse a time string e.g. (2h13m) into a timedelta object.
Modified from virhilo's answer at https://stackoverflow.com/a/4628148/851699
:param time_str: A string identifying a duration. (eg. 2h13m)
:return datetime.timedelta: A datetime.timedelta object
"""
parts = regex.match(time_str)assert parts isnotNone,"Could not parse any time information from '{}'. Examples of valid strings: '8h', '2d8h5m20s', '2m4s'".format(time_str)
time_params ={name: float(param)for name, param in parts.groupdict().items()if param}return timedelta(**time_params)
Марсель, можешь прислать мне свой адрес, чтобы я мог подать в суд? JK продолжай, любая лицензия в порядке.
Питер
Вот новое регулярное выражение; разница в "*" s: regex = re.compile (r '^ ((? P <days> [\. \ d] +?) d)? *' r '((? P <hours> [\ . \ d] +?) h)? * 'r' ((? P <минуты> [\. \ d] +?) m)? * 'r' ((? P <seconds> [\. \ d] +?) s)? $ ')
Марсель Вальдфогель
4
Django имеет служебную функцию parse_duration(). Из документации :
Разбирает строку и возвращает datetime.timedelta.
Ожидает данные в формате "DD HH:MM:SS.uuuuuu"или в соответствии с ISO 8601 (например, P4DT1H15M20Sкоторый эквивалентен 4 1:15:20) или в формате дневного интервала PostgreSQL (например 3 days 04:05:06).
d
дней,h
часов,m
минут иs
секунд , используя одну строку (после импортаdatetime
):datetime.timedelta(days = d, hours = h, minutes=m, seconds=s)
.Ответы:
Для первого формата (5hr34m56s) вы должны анализировать с помощью регулярных выражений
Вот новое решение:
источник
dateutil.parser.parse
не будет анализироватьtimedelta
объекты. Он возвращает adatetime
и вызывает исключение для таких строк, как'28:32:11.10'
.Для меня наиболее элегантным решением без использования внешних библиотек, таких как dateutil или ручного синтаксического анализа ввода, является использование мощного метода синтаксического анализа строк datetime
strptime
.После этого вы можете использовать свой объект timedelta как обычно, преобразовать его в секунды, чтобы убедиться, что мы все сделали правильно и т. Д.
источник
datetime.strptime("32:20:25","%H:%M:%S")
не работает), и вы должны знать точный формат ввода.timedelta
параметра довольно раздражает, но лучшее, что я могу придумать, чтобы избежать этого, - это:,delta = t - datetime.combine(t.date(), time.min)
что ... ужасно.У меня было немного времени на моих руках вчера, поэтому я разработал @virhilo «s ответ в модуль Python, добавив несколько времени более форматов выражений, в том числе все те , по просьбе @priestc .
Исходный код находится на github (лицензия MIT) для всех, кто этого хочет. Это также на PyPI:
Возвращает время в секундах:
источник
Я хотел ввести только время, а затем добавить его к различным датам, чтобы у меня это сработало:
источник
dtt.strptime(myduration, "%H:%M:%S") - dtt(1900, 1, 1)
тоже работает ...Я изменил хороший ответ Вирхило, добавив несколько обновлений:
3m0.25s
, 3 минуты 0,25 секунды).
источник
Django имеет служебную функцию
parse_duration()
. Из документации :источник
parse_duration()
функция Django использует регулярное выражение под капотом.Если вы используете Python 3, то вот обновленная версия решения Хари Шанкара, которое я использовал:
источник
Используйте библиотеку isodate для анализа строки продолжительности ISO 8601. Например:
Также см. Есть ли простой способ преобразовать продолжительность ISO 8601 в timedelta?
источник