265 votes

Comment puis-je analyser une chaîne de temps contenant des millisecondes avec python ?

Je suis capable d'analyser des chaînes contenant des dates et des heures 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 puis-je analyser une chaîne de temps qui contient 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

424voto

DNS Points 17577

Python 2.6 a ajouté une nouvelle macro strftime/strptime %f . La documentation est un peu trompeuse car elle ne mentionne que les microsecondes, mais %f analyse réellement tout fraction décimale de secondes avec jusqu'à 6 chiffres, ce qui signifie qu'il fonctionne également pour les millisecondes, voire les centisecondes ou les décisecondes.

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

Cependant, temps.struct_temps ne stocke pas réellement les millisecondes/microsecondes. Il est préférable d'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

Comme vous pouvez le voir, .123 est correctement interprété comme 123 000 microsecondes.

4 votes

Merci docs.python.org/library/datetime.html : Nouveau dans la version 2.6 : les objets time et datetime supportent un code de format %f qui s'étend au nombre de microsecondes dans l'objet, avec un décalage de zéro sur la gauche à six endroits.

5 votes

Je peux dire que la documentation Python a besoin d'être mise à jour. Docs pour le module temporel ne dit rien sur %f .

17 votes

La documentation Python, à partir de la version 2.7.3, est un peu trompeuse. Pour strptime, %f peut en fait représenter n'importe quel nombre de décimales, et pas seulement 6, comme on pourrait s'y attendre pour les microsecondes. Ainsi, le code ci-dessus analyserait 32,123 secondes et les stockerait sous la forme de 123,000µs, ce qui est ce que nous voulons.

12voto

Andrew Stern Points 388

Je sais que c'est une vieille question 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 date.

La solution si datetime ne supporte pas %f et sans avoir besoin d'un 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".

1 votes

dt.replace(microsecond=int(mSecs))

0 votes

Cela s'applique à Python 2.5 et aux versions antérieures. Python 2.6 supporte strptime '%f'.

4voto

Phil H Points 10133

Pour donner au code que La réponse de nstehr fait référence (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

1voto

MarkusQ Points 15612

Ma première idée a été d'essayer de lui passer '30/03/09 16:31:32.123' (avec un point au lieu de deux points entre les secondes et les millisecondes), mais cela n'a pas fonctionné. Un rapide coup d'œil à la documentation indique que les secondes fractionnaires sont ignorées dans tous les cas...

Ah, les différences de version. C'était signalé comme un bogue et maintenant, dans la version 2.6+, vous pouvez utiliser "%S.%f" pour l'analyser.

0 votes

Cela ne fonctionne pas ; time.strptime ne prend pas en compte les millisecondes.

1voto

nstehr Points 2775

À partir des listes de diffusion python : analyse du fil de la milliseconde . Il y a une fonction postée là qui semble faire le travail, bien que, comme mentionné dans les commentaires de l'auteur, ce soit une sorte de hack. Elle utilise des expressions régulières pour gérer l'exception qui est levée, puis effectue quelques calculs.

Vous pouvez aussi essayer de faire les expressions régulières et les calculs en amont, avant de les passer à strptime.

0 votes

Oui, je connais ce fil. Mais je cherche un moyen plus simple. Existe-t-il un module dans la librairie python standard qui permet d'analyser le temps en millisecondes ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X