Come posso analizzare una stringa temporale contenente millisecondi con Python?


204

Sono in grado di analizzare le stringhe contenenti data / ora con time.strptime

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

Come posso analizzare una stringa temporale che contiene millisecondi?

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

Risposte:


318

Python 2.6 ha aggiunto una nuova macro strftime / strptime %f, che esegue microsecondi. Non sono sicuro se questo è documentato ovunque. Ma se stai usando 2.6 o 3.0, puoi farlo:

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

Modifica: non lavoro mai davvero con il timemodulo, quindi all'inizio non me ne sono accorto, ma sembra che time.struct_time in realtà non memorizzi millisecondi / microsecondi. Potrebbe essere meglio usare datetime, in questo modo:

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

4
Grazie docs.python.org/library/datetime.html : Novità nella versione 2.6: gli oggetti time e datetime supportano un codice in formato% f che si espande al numero di microsecondi nell'oggetto, con spaziatura zero a sinistra in sei posizioni.
ilkinulas,

5
Woa, posso dire che i documenti di Python devono essere aggiornati. Documenti per il modulo orario non dicono nulla %f.
phunehehe,

14
I documenti Python, a partire dalla versione 2.7.3, sono un po 'fuorvianti. Per il periodo di tempo,% f può effettivamente rappresentare un numero qualsiasi di cifre decimali, non solo 6, come ci si potrebbe aspettare per i microsecondi. Quindi il codice sopra analizzerebbe 32.123 secondi e lo memorizzerebbe come 123.000 µs, che è quello che vogliamo.
Michael Scheper,

9
Il numero in %fè riempito con zeri a destra (non a sinistra!) Con 6 cifre decimali. 1 viene analizzato a 100000, 12 viene analizzato a 120000 e 1234567 produceValueError: unconverted data remains: 7
user443854

17
Sono solo io o la domanda sui millisecondi, non sui microsecondi?
Purrell,

12

So che questa è una domanda più vecchia, ma sto ancora usando Python 2.4.3 e avevo bisogno di trovare un modo migliore di convertire la stringa di dati in un datetime.

La soluzione se datetime non supporta% f e senza la necessità di provare / tranne è:

    (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 

Funziona con la stringa di input "2010-10-06 09: 42: 52.266000"


1
dt.replace(microsecond=int(mSecs))
Haridsv,

Questo vale per Python 2.5 e precedenti. Python 2.6 supporta strptime '% f'
smci

4

Per dare il codice a cui fa riferimento la risposta di Nstehr (dalla sua fonte ):

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

2

La risposta DNS sopra è effettivamente errata. La SO chiede millisecondi ma la risposta è microsecondi. Sfortunatamente, Python`s non ha una direttiva per millisecondi, solo microsecondi (vedi doc ), ma puoi aggirarlo aggiungendo tre zeri alla fine della stringa e analizzando la stringa come microsecondi, qualcosa del tipo:

datetime.strptime(time_str + '000', '%d/%m/%y %H:%M:%S.%f')

dove time_strè formattato come 30/03/09 16:31:32.123.

Spero che questo ti aiuti.


2
Inizialmente pensavo la stessa cosa, ma vedo i commenti sulla risposta e i documenti . Sono microsecondi a zero zero , quindi .123correttamente interpretati come 123.000 microsecondi
aschmied

1

Il mio primo pensiero è stato quello di provare a passarlo '30 / 03/09 16: 31: 32.123 '(con un punto anziché un punto tra i secondi e i millisecondi). Ma non ha funzionato. Una rapida occhiata ai documenti indica che i secondi frazionari vengono comunque ignorati ...

Ah, differenze di versione. Questo è stato segnalato come un bug e ora in 2.6+ puoi usare "% S.% f" per analizzarlo.


Questo non funziona; time.strptime non fa millisecondi.
DNS

1

dalle mailing list di Python: analisi del thread in millisecondi . C'è una funzione pubblicata lì che sembra portare a termine il lavoro, anche se come menzionato nei commenti dell'autore è una specie di hack. Utilizza espressioni regolari per gestire l'eccezione che viene sollevata, quindi esegue alcuni calcoli.

Potresti anche provare a fare le espressioni regolari e i calcoli in anticipo, prima di passarlo allo strptime.


si, conosco quel thread. Ma sto cercando un modo più semplice. c'è qualche modulo nella libreria standard di Python che rende il tempo di analisi con millisecondi?
ilkinulas,

1

Per python 2 l'ho fatto

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

stampa il tempo "% H:% M:% S", divide time.time () su due sottostringhe (prima e dopo il.) xxxxxxx.xx e poiché .xx sono i miei millisecondi aggiungo la seconda sottostringa al mio "% H:% M:% S"

spero che abbia un senso :) Esempio di output:

13: 31: 21.72 Lampeggiamento 01


13: 31: 21.81 FINE BLINK 01


13: 31: 26.3 Lampeggiamento 01


13: 31: 26.39 FINE BLINK 01


13: 31: 34.65 Inizio corsia 01


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.