web-dev-qa-db-fra.com

Conversion de datetime.date en horodatage UTC dans Python

J'ai affaire à des dates dans Python et j'ai besoin de les convertir en horodatages UTC pour pouvoir les utiliser en 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 date/heure n'aide pas non plus. J'ai essayé l'exemple à ce 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 soit:

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

ou

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

ça marche.

Question générale: comment puis-je convertir une date en secondes depuis Epoch selon UTC?

272
Andreas Jung

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 peuvent être différents si minuit dans le fuseau horaire local n'est pas la même instance horaire que minuit à l'heure UTC.

mktime() peut renvoyer un résultat incorrect si d correspond à une heure locale ambiguë (par exemple, pendant la transition de 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 plate-forme donnée. Vous pourriez tiliser le module pytz (par exemple, via tzlocal.get_localzone()) pour accéder à la base de données tz sur toutes les plateformes . En outre, utcfromtimestamp() peut échouer et mktime() peut renvoyer un horodatage non POSIX si "right" fuseau horaire est utilisé .


Pour convertir un objet datetime.date représentant la date en heure 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 convertir une date en secondes depuis Epoch au format UTC?

Pour convertir datetime.datetime (et non datetime.date), un objet qui représente déjà l'heure en UTC en fonction de l'horodatage POSIX correspondant (un float).

Python 3.3+

datetime.timestamp() :

from datetime import timezone

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

Remarque: Il est nécessaire d'indiquer explicitement timezone.utc sinon .timestamp() suppose que votre objet date/heure naïf est dans le fuseau horaire local.

Python 3 (<3.3)

Dans la documentation de datetime.utcfromtimestamp() :

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

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: époque de l’époque en fonction de l’heure du jour sur la différence entre quelle heure est-il? et Combien de secondes se sont écoulées?

Voir aussi: date-heure nécessite une méthode "Epoch"

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

Attention aux problèmes de virgule flottante .

Sortie

2012-01-08 15:34:10.022403
1326036850.02

Comment convertir un objet datetime au courant en horodatage 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()
434
jfs

Pour systèmes Unix uniquement:

>>> import datetime
>>> d = datetime.date(2011,01,01)
>>> d.strftime("%s")  # <-- THIS IS THE CODE YOU WANT
'1293832800'

Remarque 1: dizzyf a observé que cela s'applique aux fuseaux horaires localisés. Ne pas utiliser dans la production.

Note 2: Jakub Narębski a noté que cela ignore les informations de fuseau horaire même pour les dates/heures sensibles à l'offset (testé pour Python 2,7).

72
Ulf Aslak
  • Hypothèse 1: Vous essayez de convertir une date en un horodatage, mais comme une date couvre une période de 24 heures, aucun horodatage ne représente cette date. Je suppose que vous souhaitez 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 à partir d'un fuseau horaire particulier (UTC). Sans connaître le fuseau horaire dans lequel se trouve la date, il est impossible de calculer un horodatage pour un fuseau horaire spécifique. Je suppose 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 divers composants de l'heure à l'aide du membre timetuple():

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 convertir cela 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 de l'époque elle-même (1970-01-01). Dans ce 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 8 heures, ce qui serait correct pour le fuseau horaire du Pacifique (où je suis à).

37
DRH

suivez 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)
8
Wang

J'ai défini mes deux fonctions

  • utc_time2datetime (utc_time, tz = None)
  • datetime2utc_time (datetime)

ici:

import time
import datetime
from pytz import timezone
import calendar
import pytz


def utc_time2datetime(utc_time, tz=None):
    # convert utc time to utc datetime
    utc_datetime = datetime.datetime.fromtimestamp(utc_time)

    # add time zone to utc datetime
    if tz is None:
        tz_datetime = utc_datetime.astimezone(timezone('utc'))
    else:
        tz_datetime = utc_datetime.astimezone(tz)

    return tz_datetime


def datetime2utc_time(datetime):
    # add utc time zone if no time zone is set
    if datetime.tzinfo is None:
        datetime = datetime.replace(tzinfo=timezone('utc'))

    # convert to utc time zone from whatever time zone the datetime is set to
    utc_datetime = datetime.astimezone(timezone('utc')).replace(tzinfo=None)

    # create a time Tuple from datetime
    utc_timetuple = utc_datetime.timetuple()

    # create a time element from the Tuple an add microseconds
    utc_time = calendar.timegm(utc_timetuple) + datetime.microsecond / 1E6

    return utc_time
5
agittarius

Utilisation du package arrow :

>>> import arrow
>>> arrow.get(2010, 12, 31).timestamp
1293753600
>>> time.gmtime(1293753600)
time.struct_time(tm_year=2010, tm_mon=12, tm_mday=31, 
    tm_hour=0, tm_min=0, tm_sec=0, 
    tm_wday=4, tm_yday=365, tm_isdst=0)
2
Mathieu Longtin

la question est un peu confuse. les horodatages ne sont pas UTC - ils sont une chose Unix. la date pourrait être UTC? en supposant que ce soit le cas, et si vous utilisez Python 3.2+, simple-date rend ceci trivial:

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

si vous avez réellement l'année, le mois et le jour, vous n'avez pas besoin de créer la date:

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

et si la date est dans un autre fuseau horaire (c'est important parce que nous supposons minuit sans heure associée):

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

[l’idée derrière simple-date est de rassembler toutes les informations de date et d’heure de python dans une classe cohérente, de sorte que vous puissiez effectuer toutes les conversions. ainsi, par exemple, cela ira également dans l'autre sens:

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

]

2
andrew cooke

Une chaîne temporelle complète contient:

  • date
  • temps
  • utcoffset [+HHMM or -HHMM]

Par exemple:

_1970-01-01 06:00:00 +0500_ == _1970-01-01 01:00:00 +0000_ == _UNIX timestamp:3600_

_$ python3
>>> from datetime import datetime
>>> from calendar import timegm
>>> tm = '1970-01-01 06:00:00 +0500'
>>> fmt = '%Y-%m-%d %H:%M:%S %z'
>>> timegm(datetime.strptime(tm, fmt).utctimetuple())
3600
_

Note:

UNIX timestamp est un nombre à virgule flottante exprimé en secondes depuis l'époque, en UTC.


Edit:

_$ python3
>>> from datetime import datetime, timezone, timedelta
>>> from calendar import timegm
>>> dt = datetime(1970, 1, 1, 6, 0)
>>> tz = timezone(timedelta(hours=5))
>>> timegm(dt.replace(tzinfo=tz).utctimetuple())
3600
_
0
kev