Python: Comment obtenir une valeur de datetime.aujourd'hui () "fuseau horaire"?

j'essaie de soustraire une valeur de date de la valeur de datetime.today() pour calculer depuis combien de temps quelque chose était. Mais elle se plaint:

TypeError: can't subtract offset-naive and offset-aware datetimes

La valeur datetime.today() ne semble pas être le "fuseau horaire", tandis que mon autre valeur à la date de l'est. Comment puis-je obtenir une valeur de datetime.today() qui soit consciente du fuseau horaire? En ce moment, il me donne l'heure en heure locale, qui se trouve être PST, i.e. UTC-8hrs. Dans le pire des cas, y a-t-il un moyen de saisir manuellement une valeur de timezone dans l'objet datetime retourné par datetime.today() et réglé sur UTC-8? Bien sûr, l'idéal serait pour elle de connaître automatiquement le fuseau horaire.

207

14 réponses

dans la bibliothèque standard, il n'y a pas de moyen multiplate-forme pour créer des timezones conscientes sans créer votre propre classe timezone.

sur Windows , il y a win32timezone.utcnow() , mais ça fait partie de pywin32. Je suggère plutôt d'utiliser la pytz library , qui a une base de données constamment mise à jour de la plupart des fuseaux horaires.

travailler avec les fuseaux horaires locaux peut être très délicat (voir les liens "autres lectures" ci-dessous), donc vous pouvez plutôt vouloir pour utiliser UTC tout au long de votre application, en particulier pour les opérations arithmétiques comme le calcul de la différence entre deux points de temps.

Vous pouvez obtenir la date/heure actuelle comme suit:

import pytz
from datetime import datetime
datetime.utcnow().replace(tzinfo=pytz.utc)

l'Esprit que datetime.today() et datetime.now() retour local le temps, pas le temps UTC, donc l'application .replace(tzinfo=pytz.utc) pour eux ne serait pas correct.

une autre façon agréable de le faire est:

datetime.now(pytz.utc)

qui est un peu plus court et fait de même.


lectures et observations supplémentaires pourquoi préférer L'UTC dans de nombreux cas:

266
répondu AndiDog 2018-10-05 20:25:49

Obtenir l'heure actuelle, dans un fuseau horaire:

import datetime
import pytz
my_date = datetime.datetime.now(pytz.timezone('US/Pacific'))
68
répondu philfreo 2014-02-18 03:30:31

en Python 3, la bibliothèque standard la rend beaucoup plus facile:

>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2016, 8, 26, 14, 34, 34, 74823, tzinfo=datetime.timezone.utc)

si vous voulez une solution qui n'utilise que la bibliothèque standard et qui fonctionne en Python 2 et Python 3, voir réponse de J. F. Sebastien .

24
répondu Flimm 2017-05-23 11:47:28

Voici une solution stdlib qui fonctionne à la fois sur Python 2 et 3:

from datetime import datetime

now = datetime.now(utc) # timezone-aware datetime.utcnow()
today = datetime(now.year, now.month, now.day, tzinfo=utc) # midnight

today est une instance de datetime consciente représentant le début de la journée (minuit) dans UTC et utc est un objet tzinfo ( exemple du docs ):

from datetime import tzinfo, timedelta

ZERO = timedelta(0)

class UTC(tzinfo):
    def utcoffset(self, dt):
        return ZERO

    def tzname(self, dt):
        return "UTC"

    def dst(self, dt):
        return ZERO

utc = UTC()

Liées: comparaison des performances de plusieurs façons d'obtenir de minuit (le début d'une journée pour une heure UTC .

Note: c'est plus complexe, à obtenir minuit pour un fuseau horaire avec un décalage utc non fixe .

14
répondu jfs 2017-05-23 12:18:21

une Autre méthode pour construire fuseau horaire conscient objet datetime représentant l'heure actuelle:

import datetime
import pytz

pytz.utc.localize( datetime.datetime.utcnow() )  
10
répondu Dariusz Walczak 2013-02-11 05:19:28

si vous utilisez Django, vous pouvez définir des dates Non-TZ aware (seulement utc).

Commentaire la ligne suivante dans settings.py:

USE_TZ = True
8
répondu laffuste 2014-02-05 09:43:32

pytz est une bibliothèque Python qui permet des calculs précis et transversaux de fuseaux horaires utilisant Python 2.3 ou supérieur.

avec le stdlib, ce n'est pas possible.

Voir une question semblable sur DONC .

6
répondu user225312 2017-05-23 12:26:27

Voici une façon de le générer avec le stdlib:

import time
from datetime import datetime

FORMAT='%Y-%m-%dT%H:%M:%S%z'
date=datetime.strptime(time.strftime(FORMAT, time.localtime()),FORMAT)

date stockera la date locale et le offset de UTC , pas la date au fuseau horaire UTC, de sorte que vous pouvez utiliser cette solution si vous avez besoin d'identifier le fuseau horaire la date est générée à . Dans cet exemple et dans mon fuseau horaire local:

date
datetime.datetime(2017, 8, 1, 12, 15, 44, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))

date.tzname()
'UTC+02:00'

la clé est d'ajouter la directive %z le FORMAT de représentation, pour indiquer le décalage UTC de la structure temporelle générée. D'autres formats de représentation peuvent être consultés dans le module datetime docs

si vous avez besoin de la date au fuseau horaire UTC, Vous pouvez remplacer heure.localtime () avec time.gmtime ()

date=datetime.strptime(time.strftime(FORMAT, time.gmtime()),FORMAT)

date    
datetime.datetime(2017, 8, 1, 10, 23, 51, tzinfo=datetime.timezone.utc)

date.tzname()
'UTC'

Modifier

python3 . La directive z n'est pas disponible sur python 2 _strptime.py code

5
répondu jcazor 2017-08-01 10:25:57

Pourquoi ne pas utiliser dateutil comme décrit ici: http://joelinoff.com/blog/?p=802

from dateutil.tz import tzlocal
# Get the current date/time with the timezone.
now = datetime.datetime.now(tzlocal())
3
répondu G. Führ 2015-04-23 14:13:15

obtenir une date de connaissance du fuseau horaire dans utc le fuseau horaire est suffisant pour que la soustraction de date fonctionne.

mais si vous voulez une date de connaissance du fuseau horaire dans votre fuseau horaire actuel, tzlocal est le chemin à suivre:

from tzlocal import get_localzone  # pip install tzlocal
from datetime import datetime
datetime.now(get_localzone())

PS dateutil a une fonction similaire ( dateutil.tz.tzlocal ). Mais en dépit de partager le nom il a une base de code complètement différente, qui comme noté par J. F. Sebastian peut donner de mauvais résultats.

1
répondu Antony Hatchkins 2017-05-23 12:34:41

vous pouvez créer un timezone local en utilisant datetime en analysant la sortie d'un time.strftime appel qui utilise la directive %z (introduit en Python 3.3), comme montré par jcazor . Vous pouvez utiliser ce timezone pour créer une instance consciente datetime avec une doublure unique:

import time
from datetime import datetime

aware_local_now = datetime.now(
    tz=datetime.strptime(time.strftime("%z", time.localtime()), "%z").tzinfo)

print(aware_local_now)
2018-03-01 13:41:26.753644-08:00
1
répondu Mihai Capotă 2018-03-01 22:35:34

utiliser le fuseau horaire comme indiqué ci-dessous pour la date de connaissance du fuseau horaire, la date par défaut est UTC:

    from django.utils import timezone
    today = timezone.now() 
1
répondu Anupama V Iyengar 2018-09-18 13:55:04

Si vous obtenez l'heure et la date actuelles en python puis importer la date et l'heure,pytz paquet python après, vous obtiendrez date et l'heure actuelles comme..

from datetime import datetime
import pytz
import time
str(datetime.strftime(datetime.now(pytz.utc),"%Y-%m-%d %H:%M:%S%t"))
0
répondu jigar vagadiya 2017-05-03 09:57:49

une autre alternative, à mon avis meilleure, est d'utiliser Pendulum au lieu de pytz . Considérons le code simple suivant:

>>> import pendulum

>>> dt = pendulum.now().to_iso8601_string()
>>> print (dt)
2018-03-27T13:59:49+03:00
>>>

pour installer pendule et voir leur documentation, allez ici . Il a des tonnes d'options (comme simple ISO8601, RFC3339 et beaucoup d'autres support de format), de meilleures performances et ont tendance à produire du code plus simple.

0
répondu ng10 2018-03-27 11:25:22