Conversion d'une date en timestamp Unix et reconversion en python

J'ai dt = datetime(2013,9,1,11), et je voudrais obtenir un timestamp Unix de cet objet datetime.

Lorsque je fais (dt - datetime(1970,1,1)).total_seconds(), j'obtiens l'horodatage 1378033200.

Lorsque je le reconvertis en utilisant datetime.fromtimestamp, j'obtiens datetime.datetime(2013, 9, 1, 6, 0).

L'heure ne correspond pas. Qu'est-ce que j'ai manqué ici ?

Solution

Ce que vous avez manqué ici, ce sont les fuseaux horaires.

On peut supposer que vous avez cinq heures de décalage par rapport à UTC, donc 2013-09-01T11:00:00 local et 2013-09-01T06:00:00Z sont la même heure.

Vous devez lire le haut de la documentation datetime, qui explique les fuseaux horaires et les objets "naïfs" et "conscients".

Si votre date originelle naïve était UTC, la façon de la récupérer est d'utiliser utcfromtimestamp au lieu de fromtimestamp.

D'un autre côté, si votre date originelle était locale, vous n'auriez pas dû lui soustraire un timestamp UTC en premier lieu ; utilisez datetime.fromtimestamp(0) à la place.

Ou, si vous aviez un objet datetime aware, vous devez soit utiliser une époque locale (aware) des deux côtés, soit convertir explicitement vers et depuis UTC.

Si vous avez, ou pouvez mettre à jour, Python 3.3 ou plus, vous pouvez éviter tous ces problèmes en utilisant simplement la méthode timestamp au lieu d'essayer de trouver comment le faire vous-même. Et même si vous ne le faites pas, vous pouvez envisager d'emprunter son code source.

(Et si vous pouvez attendre Python 3.4, il semble que le PEP 341 soit susceptible d'être intégré à la version finale, ce qui signifie que toutes les choses dont J.F. Sebastian et moi parlions dans les commentaires devraient être réalisables avec la seule stdlib, et fonctionner de la même manière sous Unix et Windows).

Commentaires (9)

Plutôt que cette expression pour créer un timestamp POSIX à partir 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 : Un peu de suivi... Après quelques commentaires (voir ci-dessous), j'étais curieux de voir le 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 comme Mac OS X), vous trouverez le 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 la raison pour laquelle %s fonctionne sur les systèmes qu'il utilise. Mais il existe de meilleures solutions au problème du PO (qui tiennent compte des fuseaux horaires). Voir la réponse acceptée de @abarnert ici.

Commentaires (9)

Eh bien, lors de la conversion vers un timestamp unix, python se base sur UTC, mais lors de la conversion inverse, il vous donnera une date convertie dans votre fuseau horaire local.

Voir cette question/réponse ; https://stackoverflow.com/questions/18812638/get-timezone-used-by-datetime-datetime-fromtimestamp

Commentaires (0)