Guides / RuntimeWarning: DateTimeField received a naive datetime
RuntimeWarning: DateTimeField received a naive datetime
Your logs fill up with RuntimeWarning: DateTimeField Event.starts_at received a naive datetime (2026-01-12 10:00:00) while time zone support is active. Nothing crashes, but times can be wrong by hours once your server's time zone differs from yours. Fix it by always using timezone-aware datetimes.
RuntimeWarning: DateTimeField Event.starts_at received a naive datetime (2026-01-12 10:00:00)
while time zone support is active.
What it means
With USE_TZ = True, Django stores datetimes in UTC and expects them to carry a time zone. A naive datetime has none. Django guesses by assuming it's in the current time zone (TIME_ZONE) and warns you. On your laptop that guess may be right. On a server set to UTC it quietly shifts every such value. USE_TZ has defaulted to True since Django 5.0; projects created earlier may still have it off.
Why it happens
- You use
datetime.now()ordatetime.utcnow()in model defaults, views or tasks. Both return naive values. (utcnow()is deprecated since Python 3.12.) - You parse dates without a zone:
datetime.strptime(...)ordatetime(2026, 1, 12, 10, 0). - Imported data has no offset (CSV, API responses, fixtures).
- The server's time zone differs from yours, which makes the wrong guess visible only after you deploy.
The fix
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
from django.utils import timezone
# "now" - use Django's helper (aware, in UTC when USE_TZ is True):
now = timezone.now()
soon = timezone.now() + timedelta(hours=2)
# a specific wall-clock time in a known zone:
meeting = datetime(2026, 1, 12, 10, 0, tzinfo=ZoneInfo("Europe/Amsterdam"))
# make an existing naive value aware (state the zone it is in):
aware = timezone.make_aware(naive_value, ZoneInfo("Europe/Amsterdam"))
# model defaults must be callables, never a fixed value:
created = models.DateTimeField(default=timezone.now)
Settings that go with it:
USE_TZ = True
TIME_ZONE = "UTC" # store and compute in UTC; convert to local time only for display
Show local time in templates with the {% load tz %} filters ({{ value|localtime }} or timezone.activate() per user) and not by storing local values.
If your project still has USE_TZ = False, switching it on changes how existing values are read, so do it deliberately: back up, set USE_TZ = True with TIME_ZONE equal to the zone the old data was written in, and test on a copy of production.
Making it stick in production
- Turn the warning into an error in your tests, so a naive datetime fails CI and not production (Django docs):
import warnings
warnings.filterwarnings(
"error",
r"DateTimeField .* received a naive datetime",
RuntimeWarning,
r"django\.db\.models\.fields",
)
- Search your code for
datetime.now(),utcnow()anddatetime(without atzinfo, and for date strings without an offset. - Make sure your server and containers run in UTC, and let the application convert for display. Warnings like this are easier to spot with searchable logs: Django logs empty in production.
Or skip it
Django Cloud shows your app's logs in the dashboard with search and levels, so warnings like this one are easy to find, and you can fix them before a release goes live.
pip install djangocloud-cli
djangocloud deploy
Free plans are available for students, AWS Activate startups, open-source, non-profit and research projects. See how Django Cloud compares with other ways to host Django.
Django is a registered trademark of the Django Software Foundation. Django Cloud is not affiliated with or endorsed by it. Found a mistake in this guide? Tell us and we will fix it.