J'ai dt = datetime(2013,9,1,11)
, et j'aimerais obtenir un timestamp Unix de cet objet datetime.
Quand je fais (dt - datetime(1970,1,1)).total_seconds()
j'ai reçu le timestamp 1378033200
.
Lors de la reconversion avec datetime.fromtimestamp
, j’ai datetime.datetime(2013, 9, 1, 6, 0)
.
L'heure ne correspond pas. Qu'est-ce qui m'a manqué ici?
Ce que vous avez manqué ici, ce sont les fuseaux horaires.
Vraisemblablement, vous avez cinq heures de congé par rapport au temps universel coordonné (UTC), donc 2013-09-01T11: 00: 00 heure locale et 2013-09-01T06: 00: 00Z sont identiques.
Vous devez lire le haut de la datetime
docs, qui explique les fuseaux horaires et les objets "naïfs" et "conscients".
Si votre date/heure naïve d'origine était UTC, vous pouvez la récupérer en utilisant utcfromtimestamp
au lieu de fromtimestamp
.
D'un autre côté, si votre date/heure naïve d'origine était locale, vous n'auriez pas dû lui soustraire un horodatage UTC; utilisez datetime.fromtimestamp(0)
à la place.
Ou, si vous aviez un objet date/heure conscient, vous devez utiliser une époque locale (consciente) des deux côtés ou convertir explicitement en UTC.
Si vous possédez ou pouvez effectuer une mise à niveau vers Python 3.3 ou version ultérieure, vous pouvez éviter tous ces problèmes en utilisant simplement la méthode timestamp
au lieu d'essayer de comprendre comment procéder. toi même. Et même si vous ne le faites pas, vous voudrez peut-être envisager en empruntant son code source .
(Et si vous pouvez attendre Python 3.4, cela ressemble à PEP 341 est susceptible de faire partie de la version finale, ce qui signifie tout ce que JF Sebastian et moi parlions dans les commentaires devrait être faisable avec seulement la bibliothèque stdlib, et fonctionner de la même manière sous Unix et Windows.)
la solution est
import time
import datetime
d = datetime.date(2015,1,5)
unixtime = time.mktime(d.timetuple())
Plutôt que cette expression, créez un horodatage POSIX à partir de dt
,
(dt - datetime(1970,1,1)).total_seconds()
Utilisez ceci:
int(dt.strftime("%s"))
Je trouve la bonne réponse dans votre exemple en utilisant la deuxième méthode.
EDIT: Un peu 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 indique:
"Other codes may be available on your platform.
See documentation for the C library strftime function."
Alors maintenant, si nous man strftime
(sur des systèmes BSD tels que Mac OS X), vous trouverez un support pour %s
:
"%s is replaced by the number of seconds since the Epoch, UTC (see mktime(3))."
Quoi qu'il en soit, c'est pourquoi %s
fonctionne sur les systèmes qu'il utilise. Mais il existe 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 datetime python en secondes depuis Epoch, 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
Dans 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 time.mktime, car il suppose que le tuple se trouve dans votre fuseau horaire local. A la place, utilisez calendar.timegm:
>>> import datetime, calendar
>>> d = datetime.datetime(1970, 1, 1, 0, 1, 0)
>>> calendar.timegm(d.timetuple())
60
Pour travailler avec les fuseaux horaires UTC:
time_stamp = calendar.timegm(dt.timetuple())
datetime.utcfromtimestamp(time_stamp)
Vous avez manqué les informations de fuseau horaire (déjà répondu, accepté)
arrow
Le paquetage permet d'éviter cette torture avec des dates-heures; Il est déjà écrit, testé, publié en pypi, cross-python (2.6 - 3.xx).
Tout ce dont vous avez besoin: pip install arrow
(ou ajouter des dépendances)
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'
Eh bien, lors de la conversion du timestamp UN en TO, python suppose en principe le temps UTC, mais lors de la reconversion, il vous donnera une date convertie en fuseau horaire local.
Voir cette question/réponse; Récupère le fuseau horaire utilisé par datetime.datetime.fromtimestamp ()
def dt2ts(dt, utc=False):
if utc:
return calendar.timegm(dt.timetuple())
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 souhaitez utiliser l’horodatage UTC: time.mktime
uniquement pour local dt .Use calendar.timegm
est sans danger, mais dt doit définir la zone utc. Changez donc la zone en utc. Si dt en UTC, utilisez simplement calendar.timegm
.
def datetime_to_Epoch(d1):
# create 1,1,1970 in same timezone as d1
d2 = datetime(1970, 1, 1, tzinfo=d1.tzinfo)
time_delta = d1 - d2
ts = int(time_delta.total_seconds())
return ts
def Epoch_to_datetime_string(ts, tz_name="UTC"):
x_timezone = timezone(tz_name)
d1 = datetime.fromtimestamp(ts, x_timezone)
x = d1.strftime("%d %B %Y %H:%M:%S")
return x