2011-01-07 6 views
57

Estoy escribiendo una función que necesita una entrada timedelta para pasarla como una cadena. El usuario debe ingresar algo como "32m" o "2h32m", o incluso "4:13" o "5hr34m56s" ... ¿Hay alguna biblioteca o algo que ya tenga implementado este tipo de cosas?Cómo construir un objeto timedelta a partir de una cadena simple

+0

Para las personas que solo buscan construir un objeto timedelta de 'd' days,' h' hours, 'm' minutes y' s' segundos usando una línea (después de importar 'datetime'):' datetime.timedelta (days = d , horas = h, minutos = m, segundos = s) '. –

Respuesta

48

para la 4:13, y otros formatos estándar (pero si usted no sabe cuál) utilizan dateutil.parser.parse de python-dateutil

Para el primer formato (5hr34m56s), se debe analizar el uso regular de solución se basa re-expresiones

aquí:

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

Estaba pensando en algún tipo de función que podría tomar cualquier cosa que arroje y aún así ser capaz de manejar la conversión a timedelta. – priestc

+2

He agregado el ejemplo de solución basada en :) :) – virhilo

+3

No veo cómo dateutil.parser.parse puede analizar duraciones, parece que siempre devuelve una fecha y hora. ¿Qué me estoy perdiendo? – Nickolay

58

para mí la solución más elegante, sin tener que recurrir a las bibliotecas externas como dateutil o manual de análisis sintáctico de la entrada, es utilizar datetime's poderoso strptime método de análisis de cadenas.

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) 

Después de ello se puede utilizar el objeto timedelta ya que normalmente, convertirlo a segundos para asegurarse de que hicimos lo correcto, etc.

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

Tenga en cuenta que este enfoque solo funciona si el intervalo de tiempo es inferior a 24 horas ('datetime.strptime (" 32:20:25 ","% H:% M:% S ")' no funciona), y tiene que conocer el formato de entrada exacto. – verdesmarald

+0

Esta también solo una parte responde a la pregunta del OP. Si la función necesita tratar múltiples formatos, aún necesita una inspección de formato adicional (¿1 o 2?). –

+0

En caso de que se tengan que usar días, meses o años, no sería difícil expandir el formato a, p. "% Y-% m-% d_% H:% M:% S". Detalles sobre las opciones de formato disponibles en [documentos de la biblioteca] (http://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior).En este caso, sin embargo, no está muy claro para mí qué hora delta se desea, segundos desde O A.D.? De todos modos, algo en la forma de 'delta = target_date - start_date' se podría usar para especificarlo. – metakermit

41

tuve un poco de tiempo en mis manos ayer, así que desarrollé @virhilo 's answer en un módulo de Python, agregando algunos formatos de expresión de tiempo más, incluidos todos los solicitados por @priestc.

Source code is on github (Licencia MIT) para quien lo desee. Es también de PyPI:

pip install pytimeparse 

devuelve la hora como un número de segundos:

>>> from pytimeparse.timeparse import timeparse 
>>> timeparse('32m') 
1920 
>>> timeparse('2h32m') 
9120 
>>> timeparse('4:13') 
253 
>>> timeparse('5hr34m56s') 
20096 
>>> timeparse('1.2 minutes') 
72 
2

Si utiliza Python 3, entonces aquí es la versión actualizada para la solución de Hari Shankar, que utilicé:

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

Quería ingresar solo un momento y luego agregarlo a varias fechas para que esto funcionara para mí:

from datetime import datetime as dtt 

time_only = dtt.strptime('15:30', "%H:%M") - dtt.strptime("00:00", "%H:%M") 
Cuestiones relacionadas