Попередження виконання: DateTimeField отримав наївний час


310

Я намагаюся надіслати просту пошту за допомогою IPython. Я не налаштував жодної моделі, яка все ще отримує цю помилку. Що можна зробити?

Помилка: /home/sourabh/Django/learn/local/lib/python2.7/site-packages/django/db/models/fields/ init .py: 827: RuntimeWarning: DateTimeField отримав наївну дату (2013-09-04 14: 14: 13.698105), поки активна підтримка часового поясу. Попередження про виконання)

Спробував: перший крок - додати USE_TZ = Trueу файл налаштувань і встановити pytz(якщо можливо).

Помилка змінена:

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

Відповіді:


488

Проблема не в налаштуваннях Django, а в даті, переданій моделі. Ось як виглядає об’єкт із часовим поясом:

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

І ось наївний об’єкт:

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

Тож якщо ви переносите дату електронної пошти куди завгодно (а згодом вона потрапляє до якоїсь моделі), просто використовуйте Django now(). Якщо ні, то, ймовірно, виникла проблема з існуючим пакетом, який отримує дату без часового поясу, і ви можете зафіксувати пакунок, ігнорувати попередження або встановити USE_TZ на значення False.


8
Де ви пишете tzinfo=<UTC>, що таке <UTC>? Це не синтаксична конструкція, яку я бачив.
jameshfisher

4
Трохи запізнюємось на вечірку, але те, що ви бачите, виводиться з оболонки. Більш конкретно, це вихід з об'єкта типу DateTime в Repr методу, який повертає для друку інформації про об'єкт.
Джордж Гриффін

36
У місцях, де ви використовували datetime.now, змініть його timezone.nowта додайте from django.utils import timezoneвгорі.
Unoti

12
Для тих, хто все ще шукає цю частину <UTC>, ви можете скористатися цим:import pytz datetime.datetime(2013, 11, 20, 20, 8, 7, 127325, tzinfo=pytz.UTC)
Anoyz

Мої настройки USE_TZ = True, TIME_ZONE = 'UTC'. Але коли я timezone.now()його використовую, він не відображається tzinfo=<UTC>.... Отже, цей об'єкт дати передається як наївний. Чому це відбувається?
користувач3595632

71

Використовуйте функцію django.utils.timezone.make_aware, щоб усвідомити часовий пояс ваших наївних об'єктів дати та уникнути цих попереджень.

Він перетворює наївний об'єкт дати (без інформації про часовий пояс) в той, який містить інформацію про часовий пояс (використовуючи часовий пояс, вказаний у ваших налаштуваннях django, якщо ви не вказуєте його явно як другий аргумент):

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>

Дякую за цю відповідь, це найбільш сумісний з джанго спосіб перетворення наївних дат у дати з часовим поясом моїх налаштувань
джанго

Чи можна помістити це в models.py?
Флорент

@Florent немає необхідності нічого змінювати в моделях, якщо ви використовуєте часовий пояс utc за замовчуванням, auto_nowі він auto_now_addбуде добре працювати для полів дати. Якщо вам потрібно з якихось причин ознайомитись із часовим поясом поточного об’єкта дати в моделях - використовуйте django.utils.timezone.now()функцію.
dmrz

26

Просто, щоб виправити помилку, щоб встановити поточний час

from django.utils import timezone
import datetime

datetime.datetime.now(tz=timezone.utc) # you can use this value

4
а для datetime.datetime (9999, 01, 01, tzinfo = timezone.utc)
І. Єгор

IMO це найбільш практичне рішення
Рамтін

9

Можна і виправити попередження, і використовувати часовий пояс, вказаний у settings.py, який може відрізнятися від UTC.

Наприклад, у своєму settings.py у мене є:

USE_TZ = True
TIME_ZONE = 'Europe/Paris'

Ось рішення; Перевага в тому, що str(mydate)дає правильний час:

>>> 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_aware, див. Пост dmrz.



3

Ви також можете змінити налаштування, особливо корисні в тестах:

from django.test import override_settings

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

Це не дасть вам побачити попередження, і в той же час все, що у вашому коді, що вимагає встановлення часової зони, може створити проблеми. Якщо це так, дивіться відповідь kravietz.


2

Якщо ви намагаєтесь перетворити наївний час у формат дати з часовим поясом у джанго, ось моє рішення:

>>> 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 - це наївна дата, а t2 - час дати з часовим поясом у налаштуваннях джанго.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.