web-dev-qa-db-fra.com

Convertissez date / heure en horodatage Unix et convertissez-la en python

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?

154
bridgewater

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.)

86
abarnert

la solution est

import time
import datetime
d = datetime.date(2015,1,5)

unixtime = time.mktime(d.timetuple())
123
DmitrySemenov

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.

51
Darren Stone

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
44
Francisco Costa

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
3
Matt Kramer

Pour travailler avec les fuseaux horaires UTC:

time_stamp = calendar.timegm(dt.timetuple())

datetime.utcfromtimestamp(time_stamp)
3
Emin Temiz

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)

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'
3
maxkoryukov

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 ()

2
Ronald Portier
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.

1
wyx
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
0
rjha94