RuntimeWarning: DateTimeField recebeu um datetime ingênuo

310

Estou tentando enviar um email simples usando o IPython. Eu não configurei nenhum modelo que ainda esteja recebendo esse erro. O que pode ser feito?

Erro: /home/sourabh/Django/learn/local/lib/python2.7/site-packages/django/db/models/fields/ init .py: 827: RuntimeWarning: DateTimeField recebeu um datetime ingênuo (2013-09-04 14: 14: 13.698105) enquanto o suporte ao fuso horário estiver ativo. RuntimeWarning)

Tentei: O primeiro passo é adicionar USE_TZ = Trueao seu arquivo de configurações e instalar pytz(se possível).

Erro alterado:

(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
fonte

Respostas:

490

O problema não está nas configurações do Django, mas na data passada para o modelo. Veja como é um objeto com reconhecimento de fuso horário:

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

E aqui está um objeto ingênuo:

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

Portanto, se você está passando a data do email em qualquer lugar (e eventualmente chega a algum modelo), basta usar o Django now(). Caso contrário, provavelmente é um problema com um pacote existente que busca data sem fuso horário e você pode corrigir o pacote, ignorar o aviso ou definir USE_TZ como False.

kravietz
fonte
8
Onde você escreve tzinfo=<UTC>, o que é <UTC>? Essa não é uma construção sintática que eu tenha visto.
Jameshfisher #
4
Um pouco atrasado para a festa, mas o que você está vendo é produzido pelo shell. Mais especificamente, é a saída do método repr do objeto datetime , que retorna informações imprimíveis do objeto.
George Griffin
36
Nos locais em que você estava usando datetime.now, altere para timezone.nowe adicione from django.utils import timezonena parte superior.
Jun
12
Para aqueles que ainda procuram a parte <UTC>, você pode usar o seguinte:import pytz datetime.datetime(2013, 11, 20, 20, 8, 7, 127325, tzinfo=pytz.UTC)
Anoyz 2/16
Minhas definições são USE_TZ = True, TIME_ZONE = 'UTC'. Mas quando eu uso, timezone.now()ele não aparece tzinfo=<UTC>.... Portanto, esse objeto datetime é passado como ingênuo. Por que isso acontece?
User3595632
71

Use a função django.utils.timezone.make_aware para tornar seus objetos ingênuos de data e hora fusos horários cientes e evitar esses avisos.

Ele converte um objeto de data e hora ingênuo (sem informações de fuso horário) para aquele que possui informações de fuso horário (usando o fuso horário especificado nas configurações do django se você não o especificar explicitamente como um segundo argumento):

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
fonte
Obrigado por esta resposta, é a maneira mais django-compliant para transformar datas ingênuos em datas com o fuso horário das minhas configurações do Django :)
sodimel
É possível colocar isso em models.py?
Florent
@ Florent, não há necessidade de alterar nada nos modelos se você usar o utc fuso horário por padrão auto_nowe auto_now_addfuncionará bem nos campos de data e hora. Se você precisar que o fuso horário atual reconheça o objeto de data e hora nos modelos por algum motivo - use a django.utils.timezone.now()função
dmrz 29/01
26

Apenas para corrigir o erro para definir a hora atual

from django.utils import timezone
import datetime

datetime.datetime.now(tz=timezone.utc) # you can use this value
Sachin G.
fonte
4
e para datetime.datetime (9999, 01, 01, tzinfo = timezone.utc)
I. Yegor
IMO, esta é a solução mais prática
Ramtin 25/04
9

É possível corrigir o aviso e usar o fuso horário especificado em settings.py, que pode ser diferente do UTC.

Por exemplo, em meu settings.py eu tenho:

USE_TZ = True
TIME_ZONE = 'Europe/Paris'

Aqui está uma solução; a vantagem é que str(mydate)dá a hora correta:

>>> 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'

Outro método equivalente está usando make_aware, consulte dmrz post.

Edouard Thiel
fonte
3

Você também pode substituir as configurações, particularmente úteis nos testes:

from django.test import override_settings

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

Isso impedirá que você veja o aviso. Ao mesmo tempo, qualquer coisa no seu código que exija um fuso horário com reconhecimento de fuso horário pode causar problemas. Se for esse o caso, consulte a resposta kravietz.

Radtek
fonte
2

Se você está tentando transformar um datetime ingênuo em um datetime com fuso horário no django, aqui está minha solução:

>>> 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 é um datetime ingênuo e t2 é um datetime com fuso horário nas configurações do django.

hcf1425
fonte