334 votes

Conversion de datetime.date en timestamp UTC en Python

Je traite des dates en Python et j'ai besoin de les convertir en timestamps UTC pour les utiliser en Javascript. dans Javascript. Le code suivant ne fonctionne pas :

>>> d = datetime.date(2011,01,01)
>>> datetime.datetime.utcfromtimestamp(time.mktime(d.timetuple()))
datetime.datetime(2010, 12, 31, 23, 0)

Convertir d'abord l'objet date en datetime n'aide pas non plus. J'ai essayé l'exemple suivant lien de, mais :

from pytz import utc, timezone
from datetime import datetime
from time import mktime
input_date = datetime(year=2011, month=1, day=15)

et maintenant non plus :

mktime(utc.localize(input_date).utctimetuple())

ou

mktime(timezone('US/Eastern').localize(input_date).utctimetuple())

fonctionne.

Question générale : comment puis-je obtenir une date convertie en secondes depuis l'époque selon l'UTC ?

0 votes

34 votes

Je ne suis pas sûr que je serais d'accord pour le marquer comme un doublon. Bien que les solutions soient similaires, les questions ne le sont pas. La première (celle-ci) consiste à créer un horodatage à partir d'un fichier datetime.date l'autre tente de convertir une représentation de chaîne de caractères d'un fuseau horaire à un autre. En tant que personne à la recherche d'une solution à ce problème, je ne peux pas conclure que cette dernière fournira la réponse que je recherche.

6 votes

Datetime(date.year,date.month,date.day).timestamp()

505voto

J.F. Sebastian Points 102961

Si d = date(2011, 1, 1) est en UTC :

>>> from datetime import datetime, date
>>> import calendar
>>> timestamp1 = calendar.timegm(d.timetuple())
>>> datetime.utcfromtimestamp(timestamp1)
datetime.datetime(2011, 1, 1, 0, 0)

Si d est dans le fuseau horaire local :

>>> import time
>>> timestamp2 = time.mktime(d.timetuple()) # DO NOT USE IT WITH UTC DATE
>>> datetime.fromtimestamp(timestamp2)
datetime.datetime(2011, 1, 1, 0, 0)

timestamp1 et timestamp2 peut différer si minuit dans le fuseau horaire local n'est pas la même instance horaire que minuit en UTC.

mktime() peut retourner un résultat erroné si d correspond à un heure locale ambiguë (par exemple, pendant le passage à l'heure d'été) ou si d est une date passée(future) à laquelle le décalage utc aurait pu être différent et le C mktime() n'a pas accès à la base de données tz sur la plateforme donnée. Vous pouvez utiliser pytz (par exemple, via tzlocal.get_localzone() ) pour avoir accès à la base de données tz sur toutes les plateformes . Aussi, utcfromtimestamp() peut échouer et mktime() peut retourner un timestamp non-POSIX si "right" le fuseau horaire est utilisé .


Pour convertir datetime.date qui représente la date en UTC sans calendar.timegm() :

DAY = 24*60*60 # POSIX day in seconds (exact value)
timestamp = (utc_date.toordinal() - date(1970, 1, 1).toordinal()) * DAY
timestamp = (utc_date - date(1970, 1, 1)).days * DAY

Comment puis-je obtenir une date convertie en secondes depuis l'époque selon l'UTC ?

Pour convertir datetime.datetime (pas datetime.date ) qui représente déjà le temps en UTC à l'horodatage POSIX correspondant (a float ).

Python 3.3 et plus

datetime.timestamp() :

from datetime import timezone

timestamp = dt.replace(tzinfo=timezone.utc).timestamp()

Note : Il est nécessaire de fournir timezone.utc explic explic explic explic explic explic explic explic explic explic explic explic explic explic explic explic explic explic explic explic explic explic explic explic .timestamp() suppose que votre objet datetime naïf est dans le fuseau horaire local.

Python 3 (< 3.3)

Dans les documents relatifs à datetime.utcfromtimestamp() :

Il n'existe pas de méthode pour obtenir l'horodatage à partir d'une instance de datetime, mais le timestamp POSIX correspondant à une instance de datetime dt peut être facilement calculé comme suit. Pour un dt naïf :

timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1)

Et pour un dt conscient :

timestamp = (dt - datetime(1970,1,1, tzinfo=timezone.utc)) / timedelta(seconds=1)

Lecture intéressante : Heure de l'époque et heure du jour sur la différence entre Quelle heure est-il ? et Combien de secondes se sont écoulées ?

Voir aussi : datetime a besoin d'une méthode "epoch" (époque)

Python 2

Pour adapter le code ci-dessus à Python 2 :

timestamp = (dt - datetime(1970, 1, 1)).total_seconds()

timedelta.total_seconds() est équivalent à (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6 calculée avec la division réelle activée.

Exemple

from __future__ import division
from datetime import datetime, timedelta

def totimestamp(dt, epoch=datetime(1970,1,1)):
    td = dt - epoch
    # return td.total_seconds()
    return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6 

now = datetime.utcnow()
print now
print totimestamp(now)

Méfiez-vous problèmes de virgule flottante .

Sortie

2012-01-08 15:34:10.022403
1326036850.02

Comment convertir un conscient datetime à un timestamp POSIX

assert dt.tzinfo is not None and dt.utcoffset() is not None
timestamp = dt.timestamp() # Python 3.3+

Sur Python 3 :

from datetime import datetime, timedelta, timezone

epoch = datetime(1970, 1, 1, tzinfo=timezone.utc)
timestamp = (dt - epoch) / timedelta(seconds=1)
integer_timestamp = (dt - epoch) // timedelta(seconds=1)

Sur Python 2 :

# utc time = local time              - utc offset
utc_naive  = dt.replace(tzinfo=None) - dt.utcoffset()
timestamp = (utc_naive - datetime(1970, 1, 1)).total_seconds()

2 votes

Pour le cas de Python 2, pourquoi pas : timestamp = (dt - datetime.fromtimestamp(0)).total_seconds() ?

7 votes

@m01 : datetime(1970, 1, 1) est plus explicite. fromtimestamp() est incorrect ici ( dt est en UTC donc utcfromtimestamp() devrait être utilisé à la place).

0 votes

Pourquoi renvoie-t-il un nombre à virgule flottante ? et si le script n'accepte qu'un nombre entier ?

41voto

DRH Points 3773
  • Hypothèse 1 : Vous essayez de convertir une date en un horodatage, mais comme une date couvre une période de 24 heures, il n'y a pas un seul horodatage qui représente cette date. Je suppose que vous voulez représenter l'horodatage de cette date à minuit (00:00:00.000).

  • Hypothèse 2 : La date que vous présentez n'est pas associée à un fuseau horaire particulier, mais vous souhaitez déterminer le décalage par rapport à un fuseau horaire particulier (UTC). Sans connaître le fuseau horaire dans lequel se trouve la date, il n'est pas possible de calculer un horodatage pour un fuseau horaire spécifique. Je vais supposer que vous voulez traiter la date comme si elle se trouvait dans le fuseau horaire du système local.

Tout d'abord, vous pouvez convertir l'instance de date en un tuple représentant les différentes composantes temporelles à l'aide de la fonction timetuple() membre :

dtt = d.timetuple() # time.struct_time(tm_year=2011, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=1, tm_isdst=-1)

Vous pouvez ensuite le convertir en un horodatage en utilisant time.mktime :

ts = time.mktime(dtt) # 1293868800.0

Vous pouvez vérifier cette méthode en la testant avec l'heure d'époque elle-même (1970-01-01), auquel cas la fonction devrait renvoyer le décalage du fuseau horaire pour le fuseau horaire local à cette date :

d = datetime.date(1970,1,1)
dtt = d.timetuple() # time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=-1)
ts = time.mktime(dtt) # 28800.0

28800.0 est de 8 heures, ce qui serait correct pour le fuseau horaire du Pacifique (où je me trouve).

0 votes

Je ne sais pas pourquoi cela a été descendu. Il répond au problème du PO (le code fonctionnel que le PO a qualifié de "non fonctionnel"). Il ne répond pas à ma question (convertir UTC datetime.datetime à timestamp), mais quand même upvoting.

9 votes

Faites attention. L'hypothèse selon laquelle "vous voulez traiter la date comme si elle était dans le système local timezone est la racine de tous les problèmes de fuseau horaire en python. À moins d'être sûr à 100% de la localisation de la machine qui exécutera votre script et surtout si vous servez des clients qui peuvent venir de n'importe où dans le monde, partez TOUJOURS du principe que les dates sont en UTC, et faites la conversion le plus tôt possible. Cela vous évitera d'avoir des cheveux sur la tête, croyez-moi.

8voto

Wang Points 434

Suivant le document python2.7, vous devez utiliser calendar.timegm() au lieu de time.mktime()

>>> d = datetime.date(2011,01,01)
>>> datetime.datetime.utcfromtimestamp(calendar.timegm(d.timetuple()))
datetime.datetime(2011, 1, 1, 0, 0)

3 votes

En quoi est-il différent de ma réponse si d est en UTC ?

2voto

andrew cooke Points 20902

La question est un peu confuse. Les timestamps ne sont pas UTC - c'est un truc Unix. La date pourrait être UTC ? en supposant qu'elle le soit, et si vous utilisez Python 3.2+, simple-date rend cela trivial :

>>> SimpleDate(date(2011,1,1), tz='utc').timestamp
1293840000.0

si vous disposez de l'année, du mois et du jour, vous n'avez pas besoin de créer le fichier date :

>>> SimpleDate(2011,1,1, tz='utc').timestamp
1293840000.0

et si la date se trouve dans un autre fuseau horaire (ceci est important car nous supposons que minuit sans temps associé) :

>>> SimpleDate(date(2011,1,1), tz='America/New_York').timestamp
1293858000.0

[L'idée derrière simple-date est de rassembler tous les éléments de date et d'heure de Python dans une seule classe cohérente, afin que vous puissiez effectuer n'importe quelle conversion. Ainsi, par exemple, cela ira aussi dans l'autre sens :

>>> SimpleDate(1293858000, tz='utc').date
datetime.date(2011, 1, 1)

]

0 votes

SimpleDate(date(2011,1,1), tz='America/New_York') soulève NoTimezone alors que pytz.timezone('America/New_York') ne soulève aucune exception ( simple-date==0.4.8 , pytz==2014.7 ).

0 votes

Je reçois une erreur sur pip install simple-date Il semble que ce soit uniquement python3/pip3.

-1voto

filmor Points 7439

Et si

import time
from datetime import datetime, timedelta

epoch = datetime(1970, 1, 1, 0, 0, 0)
timestamp = (d + timedelta(seconds=time.timezone) - epoch).total_seconds()

EDIT J'ai ajouté les éléments manquants, mais je ne suis pas sûr du signe ;)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X