Piszę funkcję, która potrzebuje danych wejściowych timedelta do przekazania w postaci ciągu. Użytkownik musi wpisać coś w rodzaju „32 min” lub „2h32m”, a nawet „4:13” lub „5hr34m56s” ... Czy jest jakaś biblioteka lub coś, co ma już zaimplementowane tego typu rzeczy?
100
d
dni,h
godzin,m
minut is
sekund, stosując jedną linię (po imporciedatetime
)datetime.timedelta(days = d, hours = h, minutes=m, seconds=s)
.Odpowiedzi:
W przypadku pierwszego formatu (5hr34m56s) należy analizować przy użyciu wyrażeń regularnych
Oto rozwiązanie ponownie oparte:
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) if not 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) >>>
źródło
dateutil.parser.parse
nie analizujetimedelta
obiektów. Zwraca adatetime
, co spowodowałoby wyjątek dla łańcuchów, takich jak'28:32:11.10'
.Dla mnie najbardziej eleganckim rozwiązaniem, bez konieczności uciekania się do zewnętrznych bibliotek, takich jak dateutil lub ręcznego analizowania danych wejściowych, jest użycie potężnej metody analizy ciągów datetime
strptime
.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)
Następnie możesz normalnie używać obiektu timedelta, przekonwertować go na sekundy, aby upewnić się, że zrobiliśmy właściwą rzecz itp.
print(delta) assert(5*60*60+20*60+25 == delta.total_seconds())
źródło
datetime.strptime("32:20:25","%H:%M:%S")
nie działa) i musisz znać dokładny format wejściowy.timedelta
parametru jest dość irytująca, ale najlepsze, co mogę wymyślić, aby tego uniknąć, to:,delta = t - datetime.combine(t.date(), time.min)
co jest ... okropne.Miałem trochę czasu na moje ręce wczoraj, więc opracowany @virhilo „s odpowiedź do modułu Pythona, dodając kilka formatów ekspresji czasu więcej, w tym wszystkie te wymagane przez @priestc .
Kod źródłowy jest na github (licencja MIT) dla każdego, kto tego chce. Jest również na PyPI:
Zwraca czas jako liczbę sekund:
>>> from pytimeparse.timeparse import timeparse >>> timeparse('32m') 1920 >>> timeparse('2h32m') 9120 >>> timeparse('4:13') 253 >>> timeparse('5hr34m56s') 20096 >>> timeparse('1.2 minutes') 72
źródło
Chciałem wprowadzić tylko czas, a następnie dodać go do różnych dat, więc to zadziałało:
from datetime import datetime as dtt time_only = dtt.strptime('15:30', "%H:%M") - dtt.strptime("00:00", "%H:%M")
źródło
dtt.strptime(myduration, "%H:%M:%S") - dtt(1900, 1, 1)
działa również ...Zmodyfikowałem ładną odpowiedź virhilo z kilkoma ulepszeniami:
3m0.25s
3 minuty, 0,25 sekundy).
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 is not None, "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)
źródło
Django zawiera funkcję narzędziową
parse_duration()
. Z dokumentacji :źródło
parse_duration()
funkcja Django używa dopasowania wyrażenia regularnego pod maską.Jeśli używasz Pythona 3, oto zaktualizowana wersja rozwiązania Hari Shankara, z którego korzystałem:
from datetime import timedelta import re regex = re.compile(r'(?P<hours>\d+?)/' r'(?P<minutes>\d+?)/' r'(?P<seconds>\d+?)$') def parse_time(time_str): parts = regex.match(time_str) if not parts: return parts = parts.groupdict() print(parts) time_params = {} for name, param in parts.items(): if param: time_params[name] = int(param) return timedelta(**time_params)
źródło
Użyj biblioteki isodate, aby przeanalizować ciąg czasu trwania ISO 8601. Na przykład:
isodate.parse_duration('PT1H5M26S')
Zobacz także Czy istnieje łatwy sposób przekonwertowania czasu trwania ISO 8601 na timedelta?
źródło