Comment puis-je analyser une chaîne temporelle contenant des millisecondes avec Python?

204

Je suis capable d'analyser des chaînes contenant la date / l'heure avec 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)

Comment analyser une chaîne temporelle contenant des millisecondes?

>>> 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
ilkinules
la source

Réponses:

318

Python 2.6 a ajouté une nouvelle macro strftime / strptime %f, qui fait des microsecondes. Je ne sais pas si cela est documenté quelque part. Mais si vous utilisez 2.6 ou 3.0, vous pouvez le faire:

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

Edit: Je ne travaille jamais vraiment avec le timemodule, donc je ne l'ai pas remarqué au début, mais il semble que time.struct_time ne stocke pas réellement les millisecondes / microsecondes. Il vaut peut-être mieux utiliser datetime, comme ceci:

>>> from datetime import datetime
>>> a = datetime.strptime('30/03/09 16:31:32.123', '%d/%m/%y %H:%M:%S.%f')
>>> a.microsecond
123000
DNS
la source
4
Merci docs.python.org/library/datetime.html : Nouveau dans la version 2.6: les objets time et datetime prennent en charge un code au format% f qui s'étend au nombre de microsecondes dans l'objet, avec un zéro à gauche à six endroits.
ilkinulas
5
Woa je peux dire que les documents Python doivent être mis à jour. Docs pour le module de temps ne dit rien %f.
phunehehe
14
Les documents Python, à partir de la version 2.7.3, sont un peu trompeurs. Pour strptime,% f peut en fait représenter n'importe quel nombre de décimales, pas seulement 6, comme on peut s'y attendre pour les microsecondes. Ainsi, le code ci-dessus analyserait 32,123 secondes et le stockerait comme 123 000µs, ce que nous voulons.
Michael Scheper
9
Le nombre en %fest rempli de zéros à droite (pas à gauche!) À 6 décimales. 1 est analysé à 100000, 12 est analysé à 120000 et 1234567 produitValueError: unconverted data remains: 7
user443854
17
Est-ce juste moi ou était-ce la question des millisecondes, pas des microsecondes?
Purrell
12

Je sais que c'est une question plus ancienne mais j'utilise toujours Python 2.4.3 et j'avais besoin de trouver un meilleur moyen de convertir la chaîne de données en un datetime.

La solution si datetime ne prend pas en charge% f et sans avoir besoin de try / except est:

    (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 

Cela fonctionne pour la chaîne d'entrée "2010-10-06 09: 42: 52.266000"

Andrew Stern
la source
1
dt.replace(microsecond=int(mSecs))
haridsv
Cela s'applique à Python 2.5 et versions antérieures. Python 2.6 prend en charge strptime '% f'
smci
4

Pour donner le code auquel la réponse de nstehr fait référence (à partir de sa 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
Phil H
la source
2

La réponse DNS ci - dessus est en fait incorrecte. Le SO demande des millisecondes mais la réponse est pour les microsecondes. Malheureusement, Python n'a pas de directive pour les millisecondes, juste des microsecondes (voir doc ), mais vous pouvez contourner cela en ajoutant trois zéros à la fin de la chaîne et en analysant la chaîne en microsecondes, quelque chose comme:

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

time_strest formaté comme 30/03/09 16:31:32.123.

J'espère que cela t'aides.

Rafid
la source
2
J'ai pensé la même chose au début, mais voyez les commentaires sur la réponse et les documents . Il s'agit de microsecondes .123
remplies à
1

Ma première pensée a été d'essayer de le passer '30 / 03/09 16: 31: 32.123 '(avec un point au lieu d'un deux-points entre les secondes et les millisecondes.) Mais cela n'a pas fonctionné. Un rapide coup d'œil aux documents indique que les fractions de seconde sont ignorées dans tous les cas ...

Ah, les différences de version. Cela a été signalé comme un bug et maintenant en 2.6+, vous pouvez utiliser "% S.% f" pour l'analyser.

MarkusQ
la source
Ça ne marche pas; time.strptime ne fait tout simplement pas des millisecondes.
DNS
1

à partir des listes de diffusion python: analyse du thread milliseconde . Il y a une fonction publiée ici qui semble faire le travail, bien que, comme mentionné dans les commentaires de l'auteur, c'est une sorte de piratage. Il utilise des expressions régulières pour gérer l'exception qui est déclenchée, puis effectue certains calculs.

Vous pouvez également essayer de faire les expressions régulières et les calculs à l'avance, avant de les passer à strptime.

nstehr
la source
oui, je connais ce fil. Mais je cherche un moyen plus simple. y a-t-il un module dans la bibliothèque standart python qui fait l'analyse temporelle en millisecondes?
ilkinulas
1

Pour Python 2, je l'ai fait

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

il imprime le temps "% H:% M:% S", divise le time.time () en deux sous-chaînes (avant et après le.) xxxxxxx.xx et puisque .xx sont mes millisecondes j'ajoute la deuxième sous-chaîne à mon "% H:% M:% S "

espérons que cela a du sens :) Exemple de sortie:

13: 31: 21.72 Clignotement 01


13: 31: 21.81 FIN DU CLIGNOTANT 01


13: 31: 26.3 Clignotement 01


13: 31: 26.39 FIN DU BLINK 01


13: 31: 34.65 Départ Lane 01


Papatrexas
la source