2011-01-07 10 views
57

Piszę funkcję, która potrzebuje wejścia timedelta do przekazania jako ciąg znaków. Użytkownik musi wpisać "32m" lub "2h32m", a nawet "4:13" lub "5h 34m56" ... Czy istnieje biblioteka lub coś, co już zostało zaimplementowane?Jak skonstruować obiekt timedelta z prostego łańcucha

+0

Dla osób, które chcą skonstruować obiekt timedelta z 'd' dni,' h' godzin, 'm' minut i' s' sekund używając jednej linii (po zaimportowaniu 'datetime'):' datetime.timedelta (days = d , godziny = h, minuty = m, sekundy = s) '. –

Odpowiedz

48

do 4:13, a inne formaty standardowe (ale jeśli nie wiem, który z nich) korzystać dateutil.parser.parse z python-dateutil

Dla pierwszego formatu (5hr34m56s), należy przetworzyć za pomocą regularnych rozwiązanie wyrażenia

Oto ponownie oparta:

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,) 
>>> parse_time('10s') 
datetime.timedelta(0, 10) 
>>> 
+2

Zastanawiam się nad jakąś funkcją, która mogłaby zająć wszystko, co w nią rzucisz, i nadal będzie w stanie obsłużyć konwersję na timedelta. – priestc

+2

Dodałem przykład rozwiązania oparte na re :) – virhilo

+3

Nie widzę, jak Dateutil.parser.parse może analizować czasy trwania, wydaje się, że zawsze zwraca datetime. czego mi brakuje? – Nickolay

58

dla mnie najbardziej eleganckie rozwiązanie, bez konieczności uciekania się do zewnętrznych bibliotek takich jak dateutil lub ręcznie parsowania wejście, jest użycie datetime's powerful strptime Metoda analizy łańcucha.

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) 

Po tym można korzystać z obiektu timedelta jak zwykle, konwertować je do sekundy, aby upewnić się, że zrobił właściwą rzecz, itp

print(delta) 
assert(5*60*60+20*60+25 == delta.total_seconds()) 
+19

Uwaga: podejście to działa tylko wtedy, gdy czas trwania jest krótszy niż 24 godziny ('datetime.strptime (" 32:20:25 ","% H:% M:% S ")' nie działa) i musisz znać dokładny format wejściowy. – verdesmarald

+0

Ta część tylko odpowiada na pytanie OP. Jeśli funkcja musi obsługiwać wiele formatów - nadal potrzebujesz dodatkowej kontroli formatu (1 dwukropek lub 2?). –

+0

W przypadku dni, miesięcy lub lat muszą być używane, nie byłoby trudno rozwinąć się na format do np. "% Y-% m-% d_% H:% M:% S". Szczegóły dotyczące opcji formatowania dostępnych w [bibliotekach dokumentów] (http://docs.python.org/2/library/datetime.html#strftime-i -strptime-behavior).W tym jednak przypadku nie jest dla mnie jasne, jaka jest pożądana różnica czasu - sekundy od O A. D? W każdym razie, coś w rodzaju 'delta = target_date - data_początkowa' może być użyte do określenia go. – metakermit

41

miałem trochę czasu na moje ręce wczoraj więc opracowałem @virhilo 's answer do modułu Python, dodając kilka dodatkowych formatów ekspresji, w tym wszystkie wymagane przez @priestc.

Source code is on github (Licencja MIT) dla każdego, kto chce. Jest to także na PyPI:

pip install pytimeparse 

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 
2

Jeśli używasz Python 3 to tu jest zaktualizowana wersja do sporządzania roztworu Hari Shankara, który kiedyś:

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) 
3

Chciałem wprowadzić tylko godzinę, a następnie dodać ją do różnych dat, więc to działało dla mnie:

from datetime import datetime as dtt 

time_only = dtt.strptime('15:30', "%H:%M") - dtt.strptime("00:00", "%H:%M") 
Powiązane problemy