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)

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.


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>

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

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.



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.


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.