2009-03-30 47 views
147

soy capaz de analizar cadenas que contienen fecha/hora con time.strptime¿Cómo puedo analizar una cadena de tiempo que contiene milisegundos con python?

>>> import time 
>>> time.strptime('30/03/09 16:31:32', '%d/%m/%y %H:%M:%S') 
(2009, 3, 30, 16, 31, 32, 0, 89, -1) 

¿Cómo puedo analizar una cadena que contiene el tiempo milisegundos?

>>> time.strptime('30/03/09 16:31:32.123', '%d/%m/%y %H:%M:%S') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python2.5/_strptime.py", line 333, in strptime 
    data_string[found.end():]) 
ValueError: unconverted data remains: .123 

Respuesta

218

Python 2.6 añade un nuevo strftime/strptime macro %f, que hace microsegundos. No estoy seguro si esto está documentado en cualquier lugar. Pero si usted está utilizando 2.6 o 3.0, se puede hacer esto:

time.strptime('30/03/09 16:31:32.123', '%d/%m/%y %H:%M:%S.%f') 

Editar: En realidad nunca trabajo con el módulo time, por lo que no se dio cuenta de esto al principio, pero parece que time.struct_time en realidad no almacena milisegundos/microsegundos. Usted puede ser mejor usar datetime, así:

>>> from datetime import datetime 
>>> a = datetime.strptime('30/03/09 16:31:32.123', '%d/%m/%y %H:%M:%S.%f') 
>>> a.microsecond 
123000 
+3

Gracias http://docs.python.org/library/datetime.html: Nuevo en la versión 2.6: los objetos time y datetime admiten un código de formato% f que se expande a la cantidad de microsegundos en el objeto, sin relleno en el dejó a seis lugares. – ilkinulas

+5

Woa Puedo decir que los documentos de Python necesitan actualización. [Docs for the time module] (http://docs.python.org/library/time.html#time.strftime) no dice nada sobre '% f'. – phunehehe

+1

hm, cero acolchado en la * izquierda * sería incorrecto, ¿no? –

1

Mi primer pensamiento fue para tratar de pasarlo '30/03/09 16: 31: (. Con un punto en vez de dos puntos entre los segundos y los milisegundos) 32.123' Pero eso no funcionó. Un vistazo rápido a los documentos indica que los segundos fraccionarios se ignoran en cualquier caso ...

Ah, diferencias de versión. Esto era reported as a bug y ahora en 2.6+ puede usar "% S.% f" para analizarlo.

+0

Eso no funciona; time.strptime simplemente no hace milisegundos. – DNS

+0

Sí, lo vi cuando lo probé, por lo tanto, la edición. – MarkusQ

1

de las listas de correo de python: parsing millisecond thread. Hay una función publicada allí que parece hacer el trabajo, aunque como se menciona en los comentarios del autor es una especie de truco. Utiliza expresiones regulares para manejar la excepción que se genera, y luego hace algunos cálculos.

También podría intentar hacer las expresiones regulares y los cálculos por adelantado, antes de pasarlo a strptime.

+0

sí, sé ese hilo. Pero estoy buscando una manera más simple. ¿Hay algún módulo en la lib de Standart python que haga el análisis del tiempo con milisegundos? – ilkinulas

3

Para dar el código que nstehr's answer se refiere a (de its source):

def timeparse(t, format): 
    """Parse a time string that might contain fractions of a second. 

    Fractional seconds are supported using a fragile, miserable hack. 
    Given a time string like '02:03:04.234234' and a format string of 
    '%H:%M:%S', time.strptime() will raise a ValueError with this 
    message: 'unconverted data remains: .234234'. If %S is in the 
    format string and the ValueError matches as above, a datetime 
    object will be created from the part that matches and the 
    microseconds in the time string. 
    """ 
    try: 
     return datetime.datetime(*time.strptime(t, format)[0:6]).time() 
    except ValueError, msg: 
     if "%S" in format: 
      msg = str(msg) 
      mat = re.match(r"unconverted data remains:" 
          " \.([0-9]{1,6})$", msg) 
      if mat is not None: 
       # fractional seconds are present - this is the style 
       # used by datetime's isoformat() method 
       frac = "." + mat.group(1) 
       t = t[:-len(frac)] 
       t = datetime.datetime(*time.strptime(t, format)[0:6]) 
       microsecond = int(float(frac)*1e6) 
       return t.replace(microsecond=microsecond) 
      else: 
       mat = re.match(r"unconverted data remains:" 
           " \,([0-9]{3,3})$", msg) 
       if mat is not None: 
        # fractional seconds are present - this is the style 
        # used by the logging module 
        frac = "." + mat.group(1) 
        t = t[:-len(frac)] 
        t = datetime.datetime(*time.strptime(t, format)[0:6]) 
        microsecond = int(float(frac)*1e6) 
        return t.replace(microsecond=microsecond) 

     raise 
12

Sé que esto es una cuestión más viejo, pero todavía estoy usando Python 2.4.3 y necesitaba encontrar una mejor manera de convertir la cadena de datos de una fecha y hora

La solución de fecha y hora, si no soporta% f y sin necesidad de un try/except es:

(dt, mSecs) = row[5].strip().split(".") 
    dt = datetime.datetime(*time.strptime(dt, "%Y-%m-%d %H:%M:%S")[0:6]) 
    mSeconds = datetime.timedelta(microseconds = int(mSecs)) 
    fullDateTime = dt + mSeconds 

Esto funciona para la cadena de entrada "2010-10-06 09: 42: 52.266000"

+1

'dt.replace (microsecond = int (mSecs)) ' – haridsv

+0

Esto se aplica a Python 2.5 y anteriores. Python 2.6 admite strptime '% f' – smci

0

para Python 2 Hice esto

print (time.strftime("%H:%M:%S", time.localtime(time.time())) + "." + str(time.time()).split(".",1)[1]) 

imprime tiempo "% H:% M:% S" (. antes y después de la), divide la time.time() para dos subcadenas xxxxxxx.xx y ya que .xx son mis milisegundos, agrego el segundo subt cadena a mi "% H:% M:% S"

esperanza que tiene sentido :) Ejemplo de salida:

13:31:21.72 Blink 01


13:31:21.81 FIN DE BLINK 01


13: 31: 26.3 Blink 01


13: 31: 26.39 FIN DE BLINK 01


13: 31: 34.65 A partir del carril 01


Cuestiones relacionadas