web-dev-qa-db-fra.com

Python: conversion de chaîne en horodatage avec microsecondes

Je voudrais convertir le format de date de chaîne en horodatage avec microsecondes J'essaie ce qui suit mais ne donne pas le résultat attendu:

"""input string date -> 2014-08-01 04:41:52,117
expected result -> 1410748201.117"""

import time
import datetime

myDate = "2014-08-01 04:41:52,117"
timestamp = time.mktime(datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timetuple())

print timestamp
> 1410748201.0

Où sont passées les millisecondes?

11
Krilin

Il n'y a pas de créneau pour le composant microsecondes dans un tuple temporel:

>>> import time
>>> import datetime
>>> myDate = "2014-08-01 04:41:52,117"
>>> datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timetuple()
time.struct_time(tm_year=2014, tm_mon=8, tm_mday=1, tm_hour=4, tm_min=41, tm_sec=52, tm_wday=4, tm_yday=213, tm_isdst=-1)

Vous devrez les ajouter manuellement:

>>> dt = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f")
>>> time.mktime(dt.timetuple()) + (dt.microsecond / 1000000.0)
1406864512.117

L'autre méthode que vous pourriez suivre est de produire un timedelta() objet par rapport à l'époque, puis d'obtenir l'horodatage avec la méthode timedelta.total_seconds() =:

Epoch = datetime.datetime.fromtimestamp(0)
(dt - Epoch).total_seconds()

L'utilisation d'une heure locale heure locale est assez délibérée car vous avez une valeur datetime naïve (non sensible au fuseau horaire). Cette méthode peut être inexacte en fonction de l'historique de votre fuseau horaire local, cependant, voir Commentaire de J.F. Sebastian . Vous devez convertir la valeur naïve datetime en une valeur datetime sensible au fuseau horaire en utilisant d'abord votre fuseau horaire local avant de soustraire une époque sensible au fuseau horaire.

En tant que tel, il est plus facile de s'en tenir à l'approche timetuple() + microsecondes.

Démo:

>>> dt = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f")
>>> Epoch = datetime.datetime.fromtimestamp(0)
>>> (dt - Epoch).total_seconds()
1406864512.117
13
Martijn Pieters

Dans Python 3.4 et versions ultérieures, vous pouvez utiliser

timestamp = datetime.datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f").timestamp()

Cela ne nécessite pas d'importer le module time. Il utilise également moins d'étapes et devrait donc être plus rapide. Pour les anciennes versions de python les autres réponses fournies sont probablement votre meilleure option.

Cependant, l'horodatage résultant interprétera myDate en heure locale, plutôt qu'en UTC, ce qui peut provoquer des problèmes si myDate a été donné en UTC.

3
user144153

Où sont passées les millisecondes?

C'est la partie facile. .timetuple() call les supprime. Vous pouvez les rajouter en utilisant l'attribut .microsecond. La méthode datetime.timestamp() de la bibliothèque standard fonctionne de cette façon pour les objets datetime naïfs:

def timestamp(self):
    "Return POSIX timestamp as float"
    if self._tzinfo is None:
        return _time.mktime((self.year, self.month, self.day,
                             self.hour, self.minute, self.second,
                             -1, -1, -1)) + self.microsecond / 1e6
    else:
        return (self - _Epoch).total_seconds()

Il suffit si possible que les erreurs de ~ 1 heure puissent être ignorées dans votre cas. Je suppose que vous voulez des microsecondes et que vous ne pouvez donc pas ignorer les erreurs de temps ~ 1 heure en silence.

Convertir correctement l'heure locale donnée sous forme de chaîne en horodatage POSIX est une tâche complexe en général. Vous pouvez convertir l'heure locale en UTC puis obtenir l'horodatage à partir de l'heure UTC .

Il y a deux problèmes principaux:

Les deux peuvent être résolus en utilisant la base de données tz (module pytz en Python):

from datetime import datetime
import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal

tz = get_localzone() # get pytz timezone corresponding to the local timezone

naive_d = datetime.strptime(myDate, "%Y-%m-%d %H:%M:%S,%f")
# a) raise exception for non-existent or ambiguous times
d = tz.localize(naive_d, is_dst=None)
## b) assume standard time, adjust non-existent times
#d = tz.normalize(tz.localize(naive_d, is_dst=False))
## c) assume DST is in effect, adjust non-existent times
#d = tz.normalize(tz.localize(naive_d, is_dst=True))
timestamp = d - datetime(1970, 1, 1, tzinfo=pytz.utc)

Le résultat est timestamp - un objet timedelta, vous pouvez le convertir en secondes, millisecondes, etc.

Différents systèmes peuvent également se comporter différemment autour/pendant les secondes intercalaires. La plupart des applications peuvent ignorer leur existence.

En général, il peut être plus simple de stocker des horodatages POSIX en plus à l'heure locale au lieu d'essayer de le deviner à partir de l'heure locale.

2
jfs