Python: Comment faire pour obtenir une valeur de type datetime.aujourd'hui() qui est “timezone conscient”?
Je suis en train de soustraire une date de valeur à partir de la valeur de datetime.today()
de calculer combien de temps il y a quelque chose a été. Mais il se plaint:
TypeError: can't subtract offset-naive and offset-aware datetimes
La valeur datetime.today()
ne semble pas être le "fuseau horaire courant", tandis que mon autre valeur à la date de l'est. Comment puis-je obtenir une valeur de datetime.today()
qui est le fuseau horaire courant? Maintenant, c'est de me donner l'heure en heure locale, qui se trouve être PST, c'est à dire UTC-8 heures. Pire des cas, est il possible que je peux entrer manuellement une valeur de timezone dans le datetime
objet renvoyé par datetime.today()
et réglez-UTC-8? Bien sûr, l'idéal serait pour elle de connaître automatiquement le fuseau horaire.
- connexes: Comment puis-je obtenir le temps UTC de “minuit” pour un fuseau horaire?
- Semble que nous pouvons utiliser
datetime.now().astimezone()
depuis Python 3.6
Vous devez vous connecter pour publier un commentaire.
Dans la bibliothèque standard, il n'y a pas de croix-plate-forme de manière à créer au courant de fuseaux horaires sans créer votre propre fuseau horaire classe.
Sur Windows, il y a
win32timezone.utcnow()
, mais cela fait partie de pywin32. Je voudrais plutôt vous suggérons d'utiliser le pytz bibliothèque, qui a constamment mise à jour de la base de données de plus de fuseaux horaires.Le travail avec les fuseaux horaires peuvent être très délicat (voir "Autres lectures" liens ci-dessous), de sorte que vous pouvez plutôt souhaitez 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:
L'esprit que
datetime.today()
etdatetime.now()
retour de la local temps, pas le temps UTC, donc l'application.replace(tzinfo=pytz.utc)
pour eux ne serait pas correct.Une autre belle façon de le faire est:
qui est un peu plus court et fait de même.
Lecture/regarder pourquoi préférer l'UTC, dans de nombreux cas:
datetime.now(pytz.utc)
au lieu dedatetime.utcnow().replace(tzinfo = pytz.utc)
?d1.replace(tzinfo=None)
, puis à l'aide dedatetime.utcnow()
pour obtenir de l'heure UTC actuelle, et puis j'ai été en mesure de soustraire les deux heures correctement. Si, il ressemble à pytz est assez facile à utiliser. Je vais probablement passer à cette question dans un proche avenir, de sorte que je peux avoir plus de flexibilité dans mon application. Merci! 🙂now(utc)
n'a pas de retour aujourd'hui (sauf si c'est à minuit UTC), il retourne l'heure courante au format UTC. Vous devez aussi.replace(hour=0, minute=0, ...)
pour obtenir le début de la journée (commedatetime.today()
)today()
renvoie l'heure actuelle, pas à minuit. Si il y a un cas d'utilisation où minuit est nécessaire, oui, le remplacement doit être fait en conséquence. Puisque la question initiale était d'environ datetime différence, je ne pense pas que minuit est nécessaire.datetime.today()
estcombine(date.today(), time())
.datetime
a deux.now()
et.today()
méthodes (comme vous l'avez souligné à juste titre) de retour (presque) la même chose. Il n'y a pas dedate.now()
méthode.date
etdatetime
les objets ne sont pas interchangeables. À l'aide d'un objet datetime au lieu d'undate
objet peut produire des bogues subtils; je ne vois pas de raison pourdatetime.today()
à exister que si elle est un doublon dedatetime.now()
.timezone.now()
au lieu dedatetime.now()
car il utilise UTC automatiquement siUSE_TZ = True
.timezone
est de trouver àdjango.utils.timezone
, de la documentation: docs.djangoproject.com/en/1.11/topics/i18n/timezonesObtenir l'heure actuelle, dans un fuseau horaire:
datetime.datetime(2016, 11, 5, 9, 43, 45, tzinfo=pytz.timezone('US/Pacific'))
et voir si c'est ce que vous attendiezdatetime.datetime(2016, 11, 5, 9, 43, 45, tzinfo=pytz.timezone('US/Pacific'))
, oui, c'est un horrible piège de Pythondatetime
API. Pour quelqu'un demandais WTF est avec le résultat, la réponse est que latzinfo
argument de ladatetime
constructeur est tout simplement cassé pourpytz
fuseaux horaires; vous devez utiliser les fuseaux horaires'.localize()
méthode pour créer fuseau horaire-conscient datetimes à la place.)En Python 3, de la bibliothèque standard, il est beaucoup plus facile de spécifier le fuseau horaire UTC comme:
Si vous voulez une solution qui n'utilise que de la bibliothèque standard, et qui fonctionne dans les deux Python 2 et Python 3, voir J. F. Sébastien, en réponse.
Voici un stdlib solution qui fonctionne sur Python 2 et 3:
où
today
est conscient datetime instance représentant le début de la journée (minuit) à l'UTC et l'utc
est un tzinfo objet (exemple à partir de la documentation):Connexes: comparaison des performances de plusieurs façons d'obtenir de minuit (le début d'une journée pour une heure UTC.
Remarque: il est plus complexe, à obtenez de minuit, pour un temps, d'une zone de non-correction d'un décalage utc.
Une autre méthode pour construire fuseau horaire conscient objet datetime représentant l'heure courante:
pytz.utc
etpytz.UTC
sont tous les deux définis (et ce sont les mêmes)replace()
ing fuseau horaire est généralement sujette à des erreurs dans la plupart des autres utilisations, tout enlocalize()
ing est la voie privilégiée pour l'attribution de fuseau horaire pour naïve horodateurs..now(pytz_timezone)
continue à travailler dans de tels cas..now(pytz_timezone)
fait exactement la même chose quelocalize(utcnow)
- d'abord il génère du courant de temps en temps UTC, puis il l'attribue à une timezone: "<...>Dans ce cas, le résultat est équivalent àtz.fromutc(datetime.utcnow().replace(tzinfo=tz))
". Les deux réponses sont correctes, et le travail toujours.pytz
par OLSON db est censé savoir comment le convertir à n'importe quel fuseau horaire du monde. Tout naïf (non-utc) heure du fuseau horaire la conscience est difficile à cause de l'ambiguïté au cours de l'heure d'été à des quarts de travail. Ce n'est pas un problème de.localize
(nourrir unis_dst
valeur qui fait que cela fonctionne pour n'importe quelle date). C'est un problème inhérent à l'heure d'été à la pratique..localize(now)
échoue.localize
est mieux quereplace
pour les non-dates utc.@..
si vous voulez de moi pour être informé de vos commentaires comme je le fais. Ce qui est faux: 1.pytz.utc.localize()
est mieux que.replace(tzinfo=pytz.utc)
-- mal 2.non_utc_tz.localize(utcnow)
est mieux que.now(non_utc_tz)
-- mal. Regardez votre first et 2nd commentaires.localize
ne s'agit pas ambigu timedates (non-utc entrée) - si vous lui donnez corrigeris_dst
paramètre. Regardez votre first commentaire.pytz.utc.localize(<naive_utc_date>)
fait exactement la même chose que<naive_utc_date>.replace(tzinfo=pytz.utc)
- ce n'est pas mon point. Si vous répétez une seule et même chose incorrecte millions de fois il l'habitude de devenir plus correct, juste à cause de cela.non_utc_tz.localize(utcnow)
fait exactement la même chose que<naive_utc_date>.replace(tzinfo=pytz.utc)
. Je ne vois pas en doute.datetime.now(tz)
fonctionne sans préciseris_dst
paramètre. Fait:.replace(tzinfo=pytz.utc)
travaille pour le fuseau horaire UTC. Fait:tz.localize(now)
peut échouer pour les non-utc fuseaux horaires. Vous pouvez lever l'ambiguïté en utilisantis_dst
(pour certains fuseaux horaires, il ne fonctionne que dans les versions récentes), mais comment pouvez-vous savoiris_dst
par programmation de toute façon? Conslusion:.now(tz)
est une meilleure option quetz.localize(now, is_dst=is_dst)
ici (vous pouvez utiliser.replace(tzinfo=pytz.utc)
pour des raisons de performances si votre profiler le dit).non_utc_tz.localize(non_utc_now, is_dst=is_dst)
. Qu'est ce que vous dites. Fait: votre conclusion n'a rien à voir avec ce que j'ai dit.replace
etlocalize
peut être utilisé pour l'affectation d'un fuseau horaire à un naïf d'horodatage. Les deux fonctionnent de la même manière lorsque l'opération est sans ambiguïté. Mais si l'affectation est ambigulocalize
est mieux, car il va vous avertir à ce sujet par la levée d'une exception qui vous pouvez vous rattraper et puis exécutez de nouveau le bon is_dst valeur si vous le connaissez (vous pouvez demander à un utilisateur final par exemple) ou de la valeur arbitraire de vous donner 50:50 chance du droit suppose.Replace
sur l'autre main vous donnera le même 50:50 de chances de la droite deviner, mais il l'habitude de vous informer à propos de l'ambiguïté.datetime.now(pytz.utc)
la meilleure façon de le faire..localize()
au lieu de.replace()
pour les fuseaux horaires avec un non-correction d'un décalage utc: Datetime Fuseau horaire de conversion à l'aide de pytzSi vous utilisez Django, vous pouvez définir les dates de non-tz courant (uniquement utc).
Commentaire la ligne suivante dans settings.py:
pytz est une bibliothèque Python qui permet la précision et de la croix-plate-forme de fuseau horaire calculs à l'aide de Python 2.3 ou supérieur.
Avec la stdlib, ce n'est pas possible.
Voir une question similaire sur DONC.
Ici est une façon de générer avec le stdlib:
date va stocker la date et l' décalage UTC, non pas de la date à le fuseau horaire UTC, de sorte que vous pouvez utiliser cette solution si vous avez besoin d'identifier qui fuseau horaire, la date est généré à. Dans cet exemple et dans mon fuseau horaire local:
La clé est l'ajout de la
%z
directive pour le FORMAT de représentation, pour indiquer le décalage UTC de temps générées struct. D'autres formats de représentation peuvent être consultés dans le module datetime docsSi vous avez besoin de la date à le fuseau horaire UTC, vous pouvez remplacer temps.localtime() avec temps.gmtime()
Modifier
Cela ne fonctionne que sur python3. Le z la directive 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
tzlocal()
fonction est toujours l'une des solutions les plus simples et devrait certainement être mentionné ici.Vous pouvez créer un local
timezone
à l'aide dedatetime
par l'analyse de la sortie d'untime.strftime
appel qui utilise le%z
directive (introduit en Python 3.3), comme illustré par jcazor. Vous pouvez l'utilisertimezone
pour créer un courantdatetime
exemple avec un one-liner:L'obtention d'un fuseau horaire-connaissance de la date de
utc
fuseau horaire est assez pour la date de soustraction de travail.Mais si vous voulez un fuseau horaire-connaissance de la date dans votre fuseau horaire,
tzlocal
est le chemin à parcourir:PS
dateutil
a une fonction similaire (dateutil.tz.tzlocal
). Mais en dépit de partage le nom, il est totalement différent de la base de code, qui, comme a noté par J. F. Sebastian peut donner de mauvais résultats.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..
Utiliser le fuseau horaire comme indiqué ci-dessous pour le fuseau horaire courant de date, par défaut est UTC:
Je suis en ajoutant que cette réponse est quelqu'un qui travaille fréquemment avec des non-UTC fuseaux horaires.
Le seul fuseau horaire qui a sa propre méthode est
timezone.utc
, mais vous pouvez fudge un fuseau horaire avec tout décalage UTC si vous avez besoin d'aide detimedelta
&timezone
, et de les forcer à l'aide de.replace
.À l'aide de
timezone(timedelta(hours=n))
que la zone est la vraie balle d'argent ici, et il a beaucoup d'autres applications utiles.Une autre alternative, dans mon esprit, mieux, à l'aide de
Pendulum
au lieu depytz
. Considérons le code simple suivant:Pour installer Pendule et de voir leur documentation, rendez-vous ici. Il ont des tonnes d'options (comme la simple ISO8601, RFC3339 et beaucoup d'autres le support du format), de meilleures performances et une tendance à céder plus simple de code.