obtenir UTC timestamp en python avec datetime

y a-t-il un moyen d'obtenir L'horodatage UTC en spécifiant la date? Ce à quoi je m'attendais:

datetime(2008, 1, 1, 0, 0, 0, 0)

devrait se traduire par

 1199145600

la création d'un objet datetime naïf signifie qu'il n'y a pas d'information de fuseau horaire. Si je regarde la documentation de datetime.utcfromtimestamp, créer un timestamp UTC signifie supprimer les informations sur les fuseaux horaires. Donc je suppose que créer un objet datetime naïf (comme je l'ai fait) résulterait en un UTC timestamp. Toutefois:

then = datetime(2008, 1, 1, 0, 0, 0, 0)
datetime.utcfromtimestamp(float(then.strftime('%s')))

résultats dans

2007-12-31 23:00:00

y a-t-il encore des informations cachées sur les fuseaux horaires dans l'objet datetime? Ce que je fais mal?

58
demandé sur pat 2011-02-21 17:36:30

8 réponses

Qu'est-ce qu'un naïf datetime ?

par défaut datetime les objets sont dits "naïfs": ils conservent des informations sur l'heure sans les informations sur les fuseaux horaires. Pensez à naïf datetime comme un nombre relatif (i.e.: +4 ) sans une origine claire (en fait votre origine sera commune dans toute la limite de votre système). Pensez à conscient datetime comme des nombres absolus (i.e.: 8 ) avec une origine commune pour l'ensemble monde.

Sans informations sur le fuseau horaire vous ne pouvez pas convertir les "naïfs" datetime à l'égard de tout non-naïf temps de la représentation (d'où +4 objectifs si nous ne savons pas où commencer ?). C'est pourquoi vous ne pouvez pas avoir une méthode datetime.datetime.toutctimestamp() . (cf: http://bugs.python.org/issue1457227 )

pour vérifier si votre datetime dt est naïf, cochez dt.tzinfo , si None , alors c'est naïf:

datetime.now()        ## DANGER: returns naïve datetime pointing on local time
datetime(1970, 1, 1)  ## returns naïve datetime pointing on user given time

j'ai des datetimes naïves, Que puis-je faire ?

Vous devez faire une hypothèse selon le contexte: La question que vous devez vous poser est: Est-ce que votre datetime était sur UTC ? ou était-ce l'heure locale ?

  • si vous utilisiez UTC (vous êtes hors de problème):

    import calendar
    
    def dt2ts(dt):
        """Converts a datetime object to UTC timestamp
    
        naive datetime will be considered UTC.
    
        """
    
        return calendar.timegm(dt.utctimetuple())
    
  • si vous n'utilisiez pas UTC , bienvenue en enfer.

    vous devez rendre votre datetime non-naïf avant d'utiliser le premier fonction, en leur redonnant leur fuseau horaire prévu.

    Vous aurez besoin de le nom du fuseau horaire et les informations sur l' si DST était en vigueur lors de la production de la cible naïve datetime (le dernière info sur l'heure d'été est requis pour cornercases):

    import pytz     ## pip install pytz
    
    mytz = pytz.timezone('Europe/Amsterdam')             ## Set your timezone
    
    dt = mytz.normalize(mytz.localize(dt, is_dst=True))  ## Set is_dst accordingly
    

    conséquences de ne pas fournir is_dst 1519360920":

    ne pas utiliser is_dst générera l'heure incorrecte (et UTC timestamp) si le datetime cible a été produit alors qu'un DST arrière a été mis en place (par exemple changer L'Heure de la TVD en supprimant une heure).

    fournir incorrect is_dst va bien sûr générer incorrect de temps (et d'horodatage UTC) seulement sur DST chevauchement ou des trous. Et, lorsque fournir aussi temps incorrect, se produisant dans des "trous" (temps qui n'a jamais existé en raison 1519190920 " donnera une interprétation de comment considérer ce bidon de temps, et c'est le seul cas où .normalize(..) va en fait faire quelque chose ici, comme il sera alors traduisez-le comme un temps réel valide (en changeant le datetime et le L'heure d'été l'objet, si nécessaire). Notez que .normalize() n'est pas requis pour avoir une estampille de temps UTC correcte à à la fin, mais c'est probablement recommandé si vous n'aimez pas l'idée d'avoir des faux fois dans votre variables, surtout si vous réutilisez cette variable ailleurs.

    et éviter d'utiliser le suivant: (cf: conversion du fuseau horaire en utilisant la pytz )

    dt = dt.replace(tzinfo=timezone('Europe/Amsterdam'))  ## BAD !!
    

    pourquoi? parce que .replace() remplace aveuglément le tzinfo sans en tenant compte de l'heure cible et choisira un mauvais DST objet. Alors que .localize() utilise le temps cible et votre indice is_dst pour sélectionner le bon objet DST.

ancienne réponse incorrecte (merci @J. F. Sebastien d'en avoir parlé):

avec un peu de chance, il est assez facile de deviner le fuseau horaire (votre origine locale) quand vous créez votre objet datetime naïf car il est lié à la configuration du système que vous ne changeriez pas entre la création naïve de l'objet datetime et le moment où vous voulez obtenir L'estampille temporelle UTC. Cette astuce peut être utilisée pour donner une question imparfaite .

en utilisant time.mktime nous pouvons créer un utc_mktime :

def utc_mktime(utc_tuple):
    """Returns number of seconds elapsed since epoch

    Note that no timezone are taken into consideration.

    utc tuple must be: (year, month, day, hour, minute, second)

    """

    if len(utc_tuple) == 6:
        utc_tuple += (0, 0, 0)
    return time.mktime(utc_tuple) - time.mktime((1970, 1, 1, 0, 0, 0, 0, 0, 0))

def datetime_to_timestamp(dt):
    """Converts a datetime object to UTC timestamp"""

    return int(utc_mktime(dt.timetuple()))

vous devez vous assurer que votre objet datetime est créé sur le même fuseau horaire que celui qui a créé votre datetime .

ce dernier la solution est incorrecte parce qu'elle fait l'hypothèse que le décalage UTC est désormais le même que le décalage UTC d'époque. ce qui n'est pas le cas pour beaucoup de fuseaux horaires (à un moment précis de l'année pour les décalages de L'heure D'été).

64
répondu vaab 2017-05-23 12:34:27

notez aussi le calendrier .timegm() fonction comme décrit par ce entrée de blog:

import calendar
calendar.timegm(utc_timetuple)

le résultat doit être en accord avec la solution de vaab.

18
répondu Mr. Mr. 2012-07-11 08:19:00

une autre possibilité est:

d = datetime.datetime.utcnow()
epoch = datetime.datetime(1970,1,1)
t = (d - epoch).total_seconds()

cela fonctionne à la fois comme "d" et "epoch" sont des datetimes naïves, ce qui rend l'opérateur "-" valide, et renvoie un intervalle. total_seconds() transforme l'intervalle en secondes. Notez que total_seconds() renvoie un flotteur, même d.microsecond == 0

16
répondu Chris Cogdon 2014-02-28 16:57:34

si l'objet input datetime est en UTC:

>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0)
>>> timestamp = (dt - datetime(1970, 1, 1)).total_seconds()
1199145600.0

Note: il renvoie float, c'est-à-dire que les microsecondes sont représentées par des fractions de seconde.

si l'objet Date d'entrée est en UTC:

>>> from datetime import date
>>> utc_date = date(2008, 1, 1)
>>> timestamp = (utc_date.toordinal() - date(1970, 1, 1).toordinal()) * 24*60*60
1199145600

voir plus de détails à conversion datetime.date d'horodatage UTC en Python .

12
répondu jfs 2017-05-23 12:10:08

j'ai l'impression que la réponse principale n'est toujours pas si claire, et il vaut la peine de prendre le temps de comprendre time et timezones .

la chose la plus importante à comprendre quand on traite du temps est que le temps est relatif !

  • 2017-08-30 13:23:00 : (une datetime naïve), représente une heure locale quelque part dans le monde, mais notez que 2017-08-30 13:23:00 à Londres est pas la même heure que 2017-08-30 13:23:00 à San Francisco.

parce que la même chaîne de temps peut être interprétée comme des points différents dans le temps selon où vous êtes dans le monde, il y a un besoin pour une absolue notion de temps.

A UTC timestamp est un nombre en secondes (ou millisecondes) de époque (défini comme 1 January 1970 00:00:00 à GMT fuseau horaire +00:00 décalage).

Epoch est ancré sur le fuseau horaire GMT et est donc un point absolu dans le temps. Un UTC "d'horodatage 1519200920" une offset à partir d'un temps absolu, par conséquent, définit un point absolu dans le temps .

cela permet de commander des événements dans le temps.

sans information sur le fuseau horaire, le temps est relatif et ne peut pas être converti en une notion absolue du temps sans fournir une indication de quel fuseau horaire devrait être ancré le naïf datetime.

Quels sont les types de temps utilisés dans le système informatique?

  • DateTime naïve : habituellement pour l'affichage, en heure locale (C.-à-d. dans le navigateur) où le système D'exploitation peut fournir des informations de fuseau horaire au programme.

  • UTC timestamps : un UTC timestamp est un point absolu dans le temps, comme mentionné ci-dessus, mais il est ancré dans un fuseau horaire donné, de sorte qu'un UTC timestamp peut être converti en datetime dans any timezone, cependant il ne contient pas informations de timezone. Qu'est-ce que cela signifie? Cela signifie que 1504119325 correspond à 2017-08-30T18:55:24Z , ou 2017-08-30T17:55:24-0100 ou aussi 2017-08-30T10:55:24-0800 . Il ne vous dit pas d'où vient . Il est généralement utilisé du côté du serveur pour enregistrer des événements (logs, etc...) ou utilisé pour convertir un fuseau horaire courant datetime à une point absolu dans le temps et calculer différences de temps .

  • ISO-8601 DateTime chaîne: la norme ISO-8601 est un format standardisé pour enregistrer le datetime avec le fuseau horaire. (C'est en fait plusieurs formats, lire ici: https://en.wikipedia.org/wiki/ISO_8601 ) il est utilisé pour communiquer des informations DateTime conscientes du fuseau horaire d'une manière sérialisable entre les systèmes.

quand utiliser qui? ou plutôt quand as-tu besoin de te soucier des fuseaux horaires?

  • si vous avez besoin de vous soucier de Heure de la journée , vous avez besoin d'informations sur le fuseau horaire. Un calendrier ou une alarme nécessite une heure de la journée pour fixer une réunion à l'heure correcte de la journée pour tout utilisateur dans le monde. Si ces données sont sauvegardées sur un serveur, le serveur doit savoir à quel fuseau horaire correspond le datetime.

  • pour calculer les différences de temps entre les événements provenant de différents endroits dans le monde, UTC timestamp est suffisant, mais vous perdez la capacité d'analyser à quel moment de la journée les événements se sont produits (c.-à-d. pour le web analytique, vous pouvez vouloir savoir quand les utilisateurs viennent à votre site dans leur heure locale : voyez-vous plus d'utilisateurs le matin ou le soir? Vous ne pouvez pas comprendre cela sans information sur l'Heure de la journée.

le décalage horaire dans une chaîne de date :

un autre point qui est important, est que le décalage du fuseau horaire dans une chaîne de date est Non fixe . Cela signifie que parce que 2017-08-30T10:55:24-0800 dit l'offset -0800 ou 8 heures en arrière, ne signifie pas qu'il sera toujours!

en été, il se peut qu'il fasse jour. temps, et il serait -0700

ce qui signifie que décalage du fuseau horaire (+0100) n'est pas la même chose que nom du fuseau horaire (Europe / France) ou même désignation du fuseau horaire (CET)

America/Los_Angeles timezone est un place dans le monde , mais il se transforme en PST (Pacific Standard Time) décalage horaire de notation en hiver, et PDT (heure avancée du Pacifique) en été.

donc, en plus d'obtenir le décalage du fuseau horaire à partir de la datestring, vous devriez aussi obtenir le nom du fuseau horaire pour être précis.

la plupart des paquets seront capables de convertir eux-mêmes les décalages numériques de l'heure avancée à l'heure normale, mais ce n'est pas nécessairement trivial avec juste le décalage. Par exemple WAT désignation de fuseau horaire en Afrique de l'Ouest, est UTC+0100 tout comme CET fuseau horaire en France, mais la France observe l'heure d'été, alors que l'Afrique de l'Ouest ne le fait pas (parce qu'elle est proche de l'Équateur)

bref, c'est compliqué. Très compliqué, et c'est pourquoi vous ne devriez pas le faire vous-même, mais faites confiance à un paquet qui le fait pour vous, et gardez-le à jour!

3
répondu MrE 2017-08-30 19:35:56

il y a en effet un problème avec l'utilisation de utcfromtimestamp et la spécification des fuseaux horaires. Un bel exemple/explication est disponible sur la question suivante:

comment spécifier le fuseau horaire (UTC) lors de la conversion en temps Unix? (Python)

1
répondu CamilleLDN 2017-05-23 12:26:08

la réponse acceptée ne semble pas fonctionner pour moi. Ma solution:

import time
utc_0 = int(time.mktime(datetime(1970, 01, 01).timetuple()))
def datetime2ts(dt):
    """Converts a datetime object to UTC timestamp"""
    return int(time.mktime(dt.utctimetuple())) - utc_0
0
répondu dreamingcloud 2014-02-22 06:57:44

la manière la plus simple:

>>> from datetime import datetime
>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0)
>>> dt.strftime("%s")
'1199163600'

éditer: @Daniel est correct, cela le convertirait dans le fuseau horaire de la machine. Voici une réponse révisée:

>>> from datetime import datetime, timezone
>>> epoch = datetime(1970, 1, 1, 0, 0, 0, 0, timezone.utc)
>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0, timezone.utc)
>>> int((dt-epoch).total_seconds())
'1199145600'

en fait, il n'est même pas nécessaire de préciser timezone.utc , car le décalage horaire est le même tant que datetime ont le même fuseau horaire (ou pas de fuseau horaire).

>>> from datetime import datetime
>>> epoch = datetime(1970, 1, 1, 0, 0, 0, 0)
>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0)
>>> int((dt-epoch).total_seconds())
1199145600
-1
répondu Mike Furlender 2018-03-13 18:22:50