RuntimeWarning: DateTimeField otrzymał naiwną datę i godzinę

310

Próbuję wysłać zwykłą pocztę za pomocą IPython. Nie skonfigurowałem żadnych modeli, w których nadal występuje ten błąd. Co można zrobić?

Błąd: /home/sourabh/Django/learn/local/lib/python2.7/site-packages/django/db/models/fields/ init .py: 827: RuntimeWarning: DateTimeField otrzymał naiwny datetime (2013-09-04 14: 14: 13.698105), gdy obsługa strefy czasowej jest aktywna. RuntimeWarning)

Wypróbowano: pierwszym krokiem jest dodanie USE_TZ = Truedo pliku ustawień i instalacja pytz(jeśli to możliwe).

Błąd zmieniony:

(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
źródło

Odpowiedzi:

488

Problem nie dotyczy ustawień Django, ale daty przekazanej do modelu. Oto jak wygląda obiekt uwzględniający strefę czasową:

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

A oto naiwny obiekt:

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

Więc jeśli podajesz datę e-maila w dowolnym miejscu (i ostatecznie trafia do jakiegoś modelu), po prostu użyj Django now(). Jeśli nie, to prawdopodobnie jest to problem z istniejącym pakietem, który pobiera datę bez strefy czasowej i możesz załatać pakiet, zignorować ostrzeżenie lub ustawić USE_TZ na False.

kravietz
źródło
8
Gdzie piszesz tzinfo=<UTC>, co jest <UTC>? Nie widziałem tego konstruktu składniowego.
jameshfisher
4
Trochę późno do partii, ale to, co widzisz jest wyjście z powłoki. Mówiąc dokładniej, dane wyjściowe z metody repr obiektu datetime zwracają informacje o drukowanym obiekcie.
George Griffin,
36
W miejscach, w których korzystałeś datetime.now, zmień go timezone.nowi dodaj from django.utils import timezoneu góry.
Unoti
12
Dla tych, którzy wciąż szukają tej części <UTC>, możesz użyć tego:import pytz datetime.datetime(2013, 11, 20, 20, 8, 7, 127325, tzinfo=pytz.UTC)
Anoyz
Moje ustawienia USE_TZ = True, TIME_ZONE = 'UTC'. Ale kiedy timezone.now()go używam , nie pokazuje tzinfo=<UTC>... Więc ten obiekt datetime jest przekazywany jako naiwny. Dlaczego tak się dzieje?
user3595632
71

Użyj funkcji django.utils.timezone.make_aware, aby uświadomić strefę czasową naiwnych obiektów datetime i uniknąć ostrzeżeń.

Konwertuje naiwny obiekt datetime (bez informacji o strefie czasowej) na ten, który ma informacje o strefie czasowej (używając strefy czasowej określonej w ustawieniach django, jeśli nie określisz jej jawnie jako drugiego argumentu):

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
źródło
Dzięki za odpowiedź, jest to najbardziej zgodny z django sposób na przekształcenie naiwnych dat w daty zgodnie ze
strefą
Czy można to umieścić w pliku models.py?
Florent
@Florent nie ma potrzeby zmiany czegokolwiek w modelach, jeśli domyślnie używasz strefy czasowej utc auto_nowi auto_now_addbędzie działać poprawnie dla pól datetime. Jeśli z jakiegoś powodu potrzebujesz mieć w strefie model aktualnego obiektu daty / godziny w modelach - użyj django.utils.timezone.now()funkcji.
dmrz
26

Aby naprawić błąd i ustawić aktualny czas

from django.utils import timezone
import datetime

datetime.datetime.now(tz=timezone.utc) # you can use this value
Sachin G.
źródło
4
i dla datetime.datetime (9999, 01, 01, tzinfo = timezone.utc)
I. Jegor
IMO jest to najbardziej praktyczne rozwiązanie
Ramtin
9

Można zarówno naprawić ostrzeżenie, jak i użyć strefy czasowej określonej w pliku settings.py, która może być inna niż UTC.

Na przykład w moim settings.py mam:

USE_TZ = True
TIME_ZONE = 'Europe/Paris'

Oto rozwiązanie; zaletą jest to, że str(mydate)daje właściwy czas:

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

make_awareUżywa się innej równoważnej metody , patrz post dmrz.

Edouard Thiel
źródło
3

Możesz także zastąpić ustawienia, szczególnie przydatne w testach:

from django.test import override_settings

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

Zapobiegnie to wyświetleniu ostrzeżenia, a jednocześnie wszystko w kodzie, które wymaga strefy czasowej uwzględniającej strefę czasową, może powodować problemy. Jeśli tak jest, patrz odpowiedź Kravietza.

radtek
źródło
2

Jeśli próbujesz przekształcić naiwny datetime w datetime ze strefą czasową w django, oto moje rozwiązanie:

>>> 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 to naiwna data i godzina t2 to data i strefa czasowa w ustawieniach django.

hcf1425
źródło