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.
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:
- documentation pytz
- Ce que Chaque Développeur Doit Savoir à Propos du Temps – développement des relents de nombreux cas d'utilisation
- Le Problème avec le Temps Et les fuseaux horaires - Computerphile - Drôle, explication d'ouverture des yeux sur la complexité de travailler avec des fuseaux horaires (vidéo)
Obtenir l'heure actuelle, dans un fuseau horaire:
import datetime
import pytz
my_date = datetime.datetime.now(pytz.timezone('US/Pacific'))
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 .
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
où 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 .
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() )
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
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 .
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
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())
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.
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
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()
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"))
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.