Рубрики
Software

RuntimeWarning: DateTimeField received a naive datetime

Иногда, в процессе работы с датами и фильтрации объектов возникает довольно неприятное предупреждение:

RuntimeWarning: DateTimeField Object.updated_at received a naive datetime (2020-05-05 18:02:41.675117) while time zone support is active.

Это предупреждение не останавливает выполнение скрипта, просто можно получить не совсем коректные данные в результате фильтрации.

Как исправить naive datetime?

Чтобы решить эту проблему и получить более достоверные данные, достаточно использовать пакет pytz.

Рассмотрим ситуацию. Допустим, мы хотим отфильтровать все объекты, которые изменились за последние 5 минут.

Пример, в котором мы получаем предупреждение:

import datetime
from app.models import TestObject

last_5_mins = datetime.datetime.now() - datetime.timedelta(minutes=5)
qs = TestObject.objects.filter(updated_at__gte=last_5_mins )

Используя pytz мы укажем коректный часовой пояс:

import datetime
import pytz
from app.models import TestObject

OurTZ = pytz.timezone('Europe/Kiev')

last_5_mins = datetime.datetime.now(OurTZ) - datetime.timedelta(minutes=5)
qs = TestObject.objects.filter(updated_at__gte=last_5_mins )

Теперь все хорошо, проблемы нет. Мы указали, что нужно использовать киевское время.

Naive datetime и Django. Почему так происходит?

Вызов функции datetime.now() иденичен datetime.now(tz=None) или datetime.today(). Документация: https://docs.python.org/3/library/datetime.html#datetime.datetime.now.

Все дело в том, что когда в Django включена поддержка часовых поясов, информация в БД о дате и времени храниться в формате UTC.

При этом, система использует данные в UTC, а пользователю в интерфейсе транслирует все в том часовом поясе, в котором он находиться.

Поддержка часовых поясов по умолчанию отключена. Чтобы ее включить, в settings.py указываем:

USE_TZ = True

Django использует pytz для работы с датами при включеной поддержке часовых поясов.

Модуль django.utils.timezone предоставляет функцию now(), которая возвращает текущее время в зависимости от значения параметра конфигурации USE_TZ.

Читаем справку: docs.djangoproject.com/timezones/#interpretation-of-naive-datetime-objects.