J'essaie de soustraire une valeur de date de la valeur de datetime.today()
pour calculer la date d'il y a quelque chose. Mais il se plaint:
TypeError: can't subtract offset-naive and offset-aware datetimes
La valeur datetime.today()
ne semble pas être "sensible au fuseau horaire", tandis que mon autre valeur de date l'est. Comment obtenir une valeur datetime.today()
qui soit sensible au fuseau horaire?
En ce moment, cela me donne l'heure locale, qui se trouve être PST, c'est-à-dire UTC - 8 heures. Dans le pire des cas, existe-t-il un moyen de saisir manuellement une valeur de fuseau horaire dans l' datetime
objet renvoyé par datetime.today()
et de la définir sur UTC-8?
Bien sûr, la solution idéale serait qu'il connaisse automatiquement le fuseau horaire.
datetime.now().astimezone()
depuis Python 3.6Réponses:
Dans la bibliothèque standard, il n'existe aucun moyen multiplateforme de créer des fuseaux horaires conscients sans créer votre propre classe de fuseau horaire.
Sous Windows, il y en a
win32timezone.utcnow()
, mais cela fait partie de pywin32. Je préférerais plutôt utiliser la bibliothèque pytz , qui a une base de données constamment mise à jour de la plupart des fuseaux horaires.Travailler avec des fuseaux horaires locaux peut être très délicat (voir les liens "Autres lectures" ci-dessous), vous pouvez donc préférer 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 dans le temps.
Vous pouvez obtenir la date / heure actuelle comme suit:
Gardez cela à l'esprit
datetime.today()
etdatetime.now()
renvoyez l' heure locale , pas l'heure UTC, donc leur application.replace(tzinfo=pytz.utc)
ne serait pas correcte.Une autre bonne façon de le faire est:
qui est un peu plus court et fait de même.
Pour en savoir plus / regarder pourquoi préférer l'UTC dans de nombreux cas:
la source
datetime.now(pytz.utc)
lieu dedatetime.utcnow().replace(tzinfo = pytz.utc)
?now(utc)
ne revient pas aujourd'hui (à moins qu'il soit minuit en UTC), il renvoie l'heure actuelle en UTC. Vous devez également.replace(hour=0, minute=0, ...)
obtenir le début de la journée (commedatetime.today()
)today()
renvoie l'heure actuelle, pas minuit. S'il existe un cas d'utilisation où minuit est requis, oui, le remplacement doit être effectué en conséquence. Étant donné que la question initiale portait sur la différence de datetime, je ne pense pas que minuit soit requis.datetime.today()
c'est le cascombine(date.today(), time())
.datetime
a les deux.now()
et les.today()
méthodes qui (comme vous l'avez correctement souligné) retournent (presque) la même chose. Il n'y a pas dedate.now()
méthode.date
et lesdatetime
objets ne sont pas interchangeables. L'utilisation d'un objet datetime au lieu d'undate
objet peut produire des bogues subtils; Je ne vois aucune raisondatetime.today()
d'exister s'il s'agit d'un quasi-doublon dedatetime.now()
.timezone.now()
au lieu dedatetime.now()
car il utilisera automatiquement UTC siUSE_TZ = True
.timezone
se trouve àdjango.utils.timezone
, documentation: docs.djangoproject.com/en/1.11/topics/i18n/timezonesObtenez l'heure actuelle, dans un fuseau horaire spécifique:
la source
datetime.datetime(2016, 11, 5, 9, 43, 45, tzinfo=pytz.timezone('US/Pacific'))
et voyez si c'est ce que vousDans Python 3, la bibliothèque standard facilite beaucoup plus la spécification de l'UTC comme fuseau horaire:
Si vous voulez une solution qui utilise uniquement la bibliothèque standard et qui fonctionne à la fois en Python 2 et Python 3, voir la réponse de jfs .
Si vous avez besoin du fuseau horaire local, pas de l'UTC, voir la réponse de Mihai Capotă
la source
Voici une solution stdlib qui fonctionne à la fois sur Python 2 et 3:
où
today
est une instance datetime consciente représentant le début de la journée (minuit) en UTC etutc
est un objet tzinfo ( exemple de la documentation ):Connexes: comparaison des performances de plusieurs façons d'obtenir minuit (début d'une journée) pour une heure UTC donnée . Remarque: il est plus complexe d' obtenir minuit pour un fuseau horaire avec un décalage UTC non fixe .
la source
Une autre méthode pour construire un objet datetime sensible au fuseau horaire représentant l'heure actuelle:
la source
pytz.utc
etpytz.UTC
sont tous deux définis (et sont les mêmes)replace()
le fuseau horaire ing est généralement sujet aux erreurs dans la plupart des autres utilisations, tandis que l'localize()
ing est le moyen préféré d'attribuer le fuseau horaire à des horodatages naïfs..localize()
méthode échoue pour ambiguë heure locale (entrée non-UTC). La réponse de @ philfreo qui utilise.now(pytz_timezone)
continue de fonctionner dans de tels cas..now(pytz_timezone)
fait exactement la même chose quelocalize(utcnow)
- d'abord il génère l'heure actuelle en UTC, puis il lui assigne un fuseau horaire: "<...> Dans ce cas, le résultat est équivalent àtz.fromutc(datetime.utcnow().replace(tzinfo=tz))
". Les deux réponses sont correctes et fonctionnent toujours.pytz
via OLSON db est censé savoir comment le convertir en n'importe quel fuseau horaire dans le monde. Il est difficile de prendre en compte tout autre fuseau horaire naïf (non utc) en raison de l'ambiguïté pendant les changements d'heure d'été. Ce n'est pas un problème de.localize
(lui donner uneis_dst
valeur le fait fonctionner pour n'importe quelle date). C'est un problème inhérent à la pratique de l'heure d'été.Un one-liner utilisant uniquement la bibliothèque standard fonctionne à partir de Python 3.3. Vous pouvez obtenir un
datetime
objet conscient du fuseau horaire local en utilisantastimezone
(comme suggéré par johnchen902 ):la source
datetime.now()
peut être appelé sans aucun argument et retourner le résultat local correct (les naïfsdatetime
sont présumés être dans le fuseau horaire local).Si vous utilisez Django , vous pouvez définir des dates non compatibles avec tz (uniquement UTC ).
Commentez la ligne suivante dans settings.py:
la source
pytz est une bibliothèque Python qui permet des calculs de fuseau horaire précis et multiplateforme à l'aide de Python 2.3 ou supérieur.
Avec le stdlib, ce n'est pas possible.
Voir une question similaire sur SO .
la source
Voici une façon de le générer avec stdlib:
date stockera la date locale et le décalage par rapport à UTC , pas la date au fuseau horaire UTC, vous pouvez donc utiliser cette solution si vous avez besoin d'identifier à quel fuseau horaire la date est générée . Dans cet exemple et dans mon fuseau horaire local:
La clé ajoute la
%z
directive à la représentation FORMAT, 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 la documentation du module datetimeSi vous avez besoin de la date au fuseau horaire UTC, vous pouvez remplacer time.localtime () par time.gmtime ()
Éditer
Cela ne fonctionne que sur python3 . La directive z n'est pas disponible sur le code python 2 _strptime.py
la source
Utilisez dateutil comme décrit dans Python datetime.datetime.now () qui est sensible au fuseau horaire :
la source
tzlocal()
fonction est toujours l'une des solutions les plus simples et doit certainement être mentionnée ici.Obtenir une date sensible au
utc
fuseau horaire dans le fuseau horaire suffit pour que la soustraction de date fonctionne.Mais si vous voulez une date prenant en compte le fuseau horaire dans votre fuseau horaire actuel,
tzlocal
c'est la voie à suivre:PS
dateutil
a une fonction similaire (dateutil.tz.tzlocal
). Mais malgré le partage du nom, il a une base de code complètement différente, qui, comme l'a noté JF Sebastian, peut donner de mauvais résultats.la source
Voici une solution utilisant un fuseau horaire lisible et qui fonctionne avec today ():
Vous pouvez répertorier tous les fuseaux horaires comme suit:
la source
Surtout pour les fuseaux horaires non UTC:
Le seul fuseau horaire qui a sa propre méthode est
timezone.utc
, mais vous pouvez truquer un fuseau horaire avec n'importe quel décalage UTC si vous en avez besoin en utilisanttimedelta
&timezone
, et en le forçant à l'aide.replace
.L'utilisation
timezone(timedelta(hours=n))
comme fuseau horaire est la vraie solution miracle ici, et elle a beaucoup d'autres applications utiles.la source
Si vous obtenez l'heure et la date actuelles en python, puis importez la date et l'heure, le package pytz en python après vous obtiendrez la date et l'heure actuelles comme ..
la source
Une autre alternative, dans mon esprit une meilleure, utilise à la
Pendulum
place depytz
. Considérez le code simple suivant:Pour installer Pendulum et voir leur documentation, rendez-vous ici . Il a des tonnes d'options (comme la simple prise en charge des formats ISO8601, RFC3339 et bien d'autres), de meilleures performances et a tendance à produire un code plus simple.
la source
Utilisez le fuseau horaire comme indiqué ci-dessous pour une date-heure compatible avec le fuseau horaire. La valeur par défaut est UTC:
la source
Tyler de 'howchoo' a fait un très bon article qui m'a aidé à avoir une meilleure idée des objets Datetime, lien ci-dessous
Travailler avec Datetime
essentiellement, je viens d'ajouter ce qui suit à la fin de mes deux objets datetime
Exemple:
la source
essayez pnp_datetime , tout le temps utilisé et renvoyé est avec le fuseau horaire, et ne causera aucun problème de naïf de décalage et de décalage.
la source
Il convient de souligner que depuis Python 3.6, vous n'avez besoin que de la bibliothèque standard pour obtenir un objet datetime sensible au fuseau horaire qui représente l'heure locale (le réglage de votre système d'exploitation). Utilisation de l' astimezone ()
(voir le commentaire de @ johnchen902).
la source