Convertissez datetime en timestamp Unix et convertissez-le en python
j'ai dt = datetime(2013,9,1,11)
, et je voudrais obtenir un horodatage Unix de cet objet datetime.
Quand je fais dt - datetime(1970,1,1)).total_seconds()
j'ai eu le timestamp 1378033200
.
lors de sa conversion en utilisant datetime.fromtimestamp
j'ai eu datetime.datetime(2013, 9, 1, 6, 0)
.
L'heure ne correspond pas. Qu'ai-je manqué?
9 réponses
ce que vous avez manqué ici, ce sont des fuseaux horaires.
probablement vous avez cinq heures de congé UTC, donc 2013-09-01T11:00:00 local et 2013-09-01T06:00:00Z sont la même heure.
vous devez lire le haut des datetime
docs, qui expliquent sur les fuseaux horaires et les objets" naïfs "et" conscients".
si votre DateTime naïve originale était UTC, la façon de le récupérer est d'utiliser utcfromtimestamp
au lieu de fromtimestamp
.
d'un autre côté, si votre datetime originale naïve était locale, vous n'auriez pas dû lui enlever une estampille de temps UTC; utilisez datetime.fromtimestamp(0)
à la place.
ou, si vous aviez un objet aware datetime, vous devez soit utiliser une époque locale (aware) des deux côtés, soit convertir explicitement en UTC et à partir de UTC.
Si vous avez ou pouvez mettre à niveau, Python 3.3 ou ultérieure, vous pouvez éviter tous ces problèmes en utilisant simplement la méthode timestamp
au lieu d'essayer de comprendre comment le faire vous-même. Et même si vous ne le faites pas, vous pourriez vouloir considérer en empruntant son code source .
(et si vous pouvez attendre Python 3.4, il semble que PEP 341 est susceptible de le faire dans la version finale, ce qui signifie que tout ce dont J. F. Sebastian et moi parlions dans les commentaires devrait être faisable avec juste le stdlib, et fonctionne de la même manière sur Unix et Windows.)
solution
import time
import datetime
d = datetime.date(2015,1,5)
unixtime = time.mktime(d.timetuple())
plutôt que cette expression pour créer une estampille temporelle POSIX de dt
,
(dt - datetime(1970,1,1)).total_seconds()
utilisez ceci:
int(dt.strftime("%s"))
j'obtiens la bonne réponse dans votre exemple en utilisant la deuxième méthode.
EDIT: Certains de suivi... Après quelques commentaires (Voir ci-dessous), j'étais curieux du manque de support ou de documentation pour %s
dans strftime
. Voici ce que j'ai trouvé:
dans le source Python pour datetime
et time
, la chaîne STRFTIME_FORMAT_CODES
nous dit:
"Other codes may be available on your platform.
See documentation for the C library strftime function."
donc maintenant si nous man strftime
(sur les systèmes BSD tels que Mac OS X), vous trouverez un soutien pour %s
:
"%s is replaced by the number of seconds since the Epoch, UTC (see mktime(3))."
de toute façon, c'est pourquoi %s
fonctionne sur les systèmes qu'il fait. Mais il y a de meilleures solutions au problème de L'OP (qui prennent en compte les fuseaux horaires). Voir la réponse acceptée de @abarnert ici.
si vous voulez convertir un python datetime en secondes depuis l'époque, vous devez le faire explicitement:
>>> import datetime
>>> datetime.datetime(2012,04,01,0,0).strftime('%s')
'1333234800'
>>> (datetime.datetime(2012,04,01,0,0) - datetime.datetime(1970,1,1)).total_seconds()
1333238400.0
en Python 3.3+ vous pouvez utiliser timestamp()
à la place:
>>> import datetime
>>> datetime.datetime(2012,4,1,0,0).timestamp()
1333234800.0
si votre objet datetime représente L'heure UTC, n'utilisez pas l'heure.mktime, car il suppose que le tuple est dans votre fuseau horaire local. Au lieu de cela, utiliser le calendrier.timegm:
>>> import datetime, calendar
>>> d = datetime.datetime(1970, 1, 1, 0, 1, 0)
>>> calendar.timegm(d.timetuple())
60
Eh bien, lors de la conversion en timestamp unix, python suppose fondamentalement UTC, mais tout en convertissant en arrière, il vous donnera une date convertie à votre fuseau horaire local.
voir cette question / réponse; Obtenir le fuseau horaire utilisé par datetime.datetime.fromtimestamp ()
Vous avez raté le fuseau horaire info (déjà répondu, de l'accord)
arrow
le paquet permet d'éviter cette torture avec des datetimes; il est déjà écrit, testé, pypi-publié, cross-python (2.6 - 3.XXème.)
Tout ce que vous devez: pip install arrow
(ou ajouter des dépendances)
Solution pour votre cas
dt = datetime(2013,9,1,11)
arrow.get(dt).timestamp
# >>> 1378033200
bc = arrow.get(1378033200).datetime
print(bc)
# >>> datetime.datetime(2013, 9, 1, 11, 0, tzinfo=tzutc())
print(bc.isoformat())
# >>> '2013-09-01T11:00:00+00:00'
def dt2ts(dt):
import calendar
import time
from dateutil import tz
if dt.tzinfo is None:
return int(time.mktime(dt.timetuple()))
utc_dt = dt.astimezone(tz.tzutc()).timetuple()
return calendar.timegm(utc_dt)
si vous voulez UTC timestamp: time.mktime
juste pour local dt .Utiliser calendar.timegm
est sûr mais dt doit la zone utc donc changer la zone en utc
pour travailler avec des fuseaux horaires UTC:
time_stamp = calendar.timegm(dt.timetuple())
datetime.utcfromtimestamp(time_stamp)