RuntimeWarning: DateTimeField a reçu un datetime naïf

310

J'essaie d'envoyer un simple courrier en utilisant IPython. Je n'ai pas configuré de modèle obtenant toujours cette erreur. Ce qui peut être fait?

Erreur: /home/sourabh/Django/learn/local/lib/python2.7/site-packages/django/db/models/fields/ init .py: 827: RuntimeWarning: DateTimeField a reçu un datetime naïf (2013-09-04 14: 14: 13.698105) lorsque la prise en charge du fuseau horaire est active. RuntimeWarning)

Testé: La première étape consiste à ajouter USE_TZ = Trueà votre fichier de paramètres et à installer pytz(si possible).

Erreur modifiée:

(learn)sourabh@sL:~/Django/learn/event$ python manage.py shell
/home/sourabh/Django/learn/local/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py:53: RuntimeWarning: SQLite received a naive datetime (2013-09-05 00:59:32.181872) while time zone support is active.
  RuntimeWarning)
shifu
la source

Réponses:

490

Le problème n'est pas dans les paramètres de Django, mais dans la date passée au modèle. Voici à quoi ressemble un objet sensible au fuseau horaire:

>>> from django.utils import timezone
>>> import pytz
>>> timezone.now()
datetime.datetime(2013, 11, 20, 20, 8, 7, 127325, tzinfo=pytz.UTC)

Et voici un objet naïf:

>>> from datetime import datetime
>>> datetime.now()
datetime.datetime(2013, 11, 20, 20, 9, 26, 423063)

Donc, si vous passez la date de l'e-mail n'importe où (et que cela arrive finalement à un modèle), utilisez simplement Django's now(). Sinon, c'est probablement un problème avec un package existant qui récupère la date sans fuseau horaire et vous pouvez patcher le package, ignorer l'avertissement ou définir USE_TZ sur False.

kravietz
la source
8
Où écrivez-vous tzinfo=<UTC>, qu'est-ce que c'est <UTC>? Ce n'est pas une construction syntaxique que j'ai vue.
jameshfisher
4
Un peu tard pour la fête, mais ce que vous voyez est la sortie du shell. Plus précisément, c'est la sortie de la méthode repr de l'objet datetime , qui renvoie les informations imprimables de l'objet.
George Griffin
36
Dans les endroits où vous l'utilisiez datetime.now, remplacez-le par timezone.nowet ajoutez- from django.utils import timezonele en haut.
Unoti
12
Pour ceux qui recherchent toujours cette partie <UTC>, vous pouvez utiliser ceci:import pytz datetime.datetime(2013, 11, 20, 20, 8, 7, 127325, tzinfo=pytz.UTC)
Anoyz
Mes réglages sont USE_TZ = True, TIME_ZONE = 'UTC'. Mais quand je l'utilise, timezone.now()il ne montre pas tzinfo=<UTC>.... Donc, cet objet datetime est passé comme un objet naïf. Pourquoi cela arrive-t-il?
user3595632
71

Utilisez la fonction django.utils.timezone.make_aware pour rendre vos fuseaux horaires naïfs conscients du fuseau horaire et éviter ces avertissements.

Il convertit un objet datetime naïf (sans informations de fuseau horaire) en un objet contenant des informations de fuseau horaire (en utilisant le fuseau horaire spécifié dans vos paramètres django si vous ne le spécifiez pas explicitement comme deuxième argument):

import datetime
from django.conf import settings
from django.utils.timezone import make_aware

naive_datetime = datetime.datetime.now()
naive_datetime.tzinfo  # None

settings.TIME_ZONE  # 'UTC'
aware_datetime = make_aware(naive_datetime)
aware_datetime.tzinfo  # <UTC>
dmrz
la source
Merci pour cette réponse, c'est le moyen le plus conforme à django de transformer des dates naïves en dates avec le fuseau horaire de mes paramètres django :)
sodimel
Est-il possible de mettre cela dans models.py?
Florent
@Florent il n'est pas nécessaire de changer quoi que ce soit dans les modèles si vous utilisez le fuseau horaire utc par défaut, auto_nowet auto_now_addfonctionnera bien pour les champs datetime. Si vous devez avoir un objet datetime actuel sensible au fuseau horaire dans les modèles pour une raison quelconque, utilisez la django.utils.timezone.now()fonction
dmrz
26

Juste pour corriger l'erreur pour régler l'heure actuelle

from django.utils import timezone
import datetime

datetime.datetime.now(tz=timezone.utc) # you can use this value
Sachin G.
la source
4
et pour datetime.datetime (9999, 01, 01, tzinfo = timezone.utc)
I. Yegor
OMI c'est la solution la plus pratique
Ramtin
9

On peut à la fois corriger l'avertissement et utiliser le fuseau horaire spécifié dans settings.py, qui peut être différent de l'UTC.

Par exemple dans mon settings.py j'ai:

USE_TZ = True
TIME_ZONE = 'Europe/Paris'

Voici une solution; l'avantage est que cela str(mydate)donne l'heure correcte:

>>> from datetime import datetime
>>> from django.utils.timezone import get_current_timezone
>>> mydate = datetime.now(tz=get_current_timezone())
>>> mydate
datetime.datetime(2019, 3, 10, 11, 16, 9, 184106, 
    tzinfo=<DstTzInfo 'Europe/Paris' CET+1:00:00 STD>)
>>> str(mydate)
'2019-03-10 11:16:09.184106+01:00'

Une autre méthode équivalente utilise make_aware, voir dmrz post.

Edouard Thiel
la source
5

Rapide et sale - Éteignez-le:

USE_TZ = False

dans votre settings.py

gies0r
la source
1
Lorsque USE_TZ a la valeur True et que la base de données prend en charge les fuseaux horaires (par exemple PostgreSQL), c'est une erreur de définir cette option docs.djangoproject.com/en/2.2/ref/settings/#time-zone
Marcaum54
3

Vous pouvez également remplacer les paramètres, particulièrement utiles dans les tests:

from django.test import override_settings

with override_settings(USE_TZ=False):
    # Insert your code that causes the warning here
    pass

Cela vous évitera de voir l'avertissement, en même temps, tout élément de votre code qui nécessite un datetime sensible au fuseau horaire peut vous poser des problèmes. Si tel est le cas, voir la réponse du kravietz.

radtek
la source
2

Si vous essayez de transformer un datetime naïf en un datetime avec fuseau horaire dans django, voici ma solution:

>>> import datetime
>>> from django.utils import timezone
>>> t1 = datetime.datetime.strptime("2019-07-16 22:24:00", "%Y-%m-%d %H:%M:%S")
>>> t1
    datetime.datetime(2019, 7, 16, 22, 24)
>>> current_tz = timezone.get_current_timezone()
>>> t2 = current_tz.localize(t1)
>>> t2
    datetime.datetime(2019, 7, 16, 22, 24, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)
>>>

t1 est un datetime naïf et t2 est un datetime avec un fuseau horaire dans les paramètres de django.

hcf1425
la source