Skip to main content

Python Django: How to Set the Timezone in Django

Handling timezones correctly is critical for any Django application that serves users across different regions or needs to store and display accurate timestamps. Misconfigured timezone settings can lead to confusing discrepancies in event schedules, log entries, and user-facing dates.

This guide walks you through configuring the default timezone, working with timezone-aware datetime objects, and supporting user-specific timezones in Django.

Setting the Default Timezone in Django Settings

Configuring TIME_ZONE

The most fundamental step is setting the TIME_ZONE variable in your settings.py file. This defines the default timezone your Django application uses for display and form input interpretation.

# settings.py

TIME_ZONE = 'America/New_York'

Django uses the IANA time zone database for timezone names. Some commonly used values include:

Timezone NameRegion
UTCCoordinated Universal Time
America/New_YorkEastern Time (US)
Europe/LondonGreenwich Mean Time / BST
Asia/TokyoJapan Standard Time
Asia/KolkataIndia Standard Time

Enabling Timezone Support with USE_TZ

To ensure Django handles timezone conversions properly, set USE_TZ to True in your settings.py:

# settings.py

USE_TZ = True

When USE_TZ = True, Django:

  • Stores all DateTimeField values in UTC in the database.
  • Converts datetime values to the timezone specified in TIME_ZONE when rendering templates or forms.
  • Makes timezone.now() return a timezone-aware datetime object in UTC.
warning

If USE_TZ is set to False, Django stores naive (timezone-unaware) datetime objects. This can cause serious bugs in applications that serve users in multiple timezones. Always keep USE_TZ = True unless you have a very specific reason not to.

Working with Timezone-Aware Datetime Objects

Getting the Current Time

Django's timezone module provides utility functions for creating and manipulating timezone-aware datetime objects:

from django.utils import timezone

# Returns the current time as a timezone-aware datetime in UTC
now = timezone.now()
print(now)
# Example output: 2025-07-23 14:30:00+00:00

Converting to a Different Timezone

You can convert a UTC datetime to any other timezone using astimezone():

from django.utils import timezone
import zoneinfo

now = timezone.now()

# Convert to Eastern Time
eastern = zoneinfo.ZoneInfo('America/New_York')
now_eastern = now.astimezone(eastern)
print(now_eastern)
# Example output: 2025-07-23 10:30:00-04:00

# Convert to Tokyo time
tokyo = zoneinfo.ZoneInfo('Asia/Tokyo')
now_tokyo = now.astimezone(tokyo)
print(now_tokyo)
# Example output: 2025-07-23 23:30:00+09:00
tip

Starting with Python 3.9 and Django 4.0+, the recommended approach is to use zoneinfo.ZoneInfo from the standard library instead of pytz. If you are on an older version of Python, you can install the backports.zoneinfo package or continue using pytz.

Common Mistake: Using Naive Datetime Objects

A frequent error is using Python's datetime.now() instead of Django's timezone.now(), which creates a naive datetime without timezone information:

from datetime import datetime

# WRONG: creates a naive datetime (no timezone info)
naive_now = datetime.now()
print(naive_now)
# Output: 2025-07-23 10:30:00 (no +00:00 offset)

When you try to save a naive datetime to a DateTimeField with USE_TZ = True, Django raises a warning:

RuntimeWarning: DateTimeField received a naive datetime while time zone support is active.

The correct approach:

from django.utils import timezone

# CORRECT: creates a timezone-aware datetime in UTC
aware_now = timezone.now()
print(aware_now)
# Output: 2025-07-23 14:30:00+00:00
danger

Never use datetime.datetime.now() or datetime.datetime.utcnow() in a Django project with USE_TZ = True. Always use django.utils.timezone.now() to get the current timezone-aware time.

Using localtime in Models

When displaying datetime fields to users, use Django's localtime function to convert stored UTC values to the active timezone:

from django.db import models
from django.utils.timezone import localtime


class Event(models.Model):
name = models.CharField(max_length=200)
start_time = models.DateTimeField()

def get_local_start_time(self):
"""Return start_time converted to the currently active timezone."""
return localtime(self.start_time)

def __str__(self):
return f"{self.name} at {self.get_local_start_time()}"

The localtime() function converts the datetime to whichever timezone is currently active: either the default TIME_ZONE from settings or a timezone activated via timezone.activate().

Handling User-Specific Timezones

For applications with a global user base, you may want each user to see dates and times in their own timezone.

Step 1: Add a Timezone Field to the User Profile

Create a profile model that stores each user's timezone preference:

import zoneinfo
from django.db import models
from django.conf import settings

TIMEZONE_CHOICES = [
(tz, tz) for tz in sorted(zoneinfo.available_timezones())
]


class UserProfile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='profile'
)
timezone = models.CharField(
max_length=63,
choices=TIMEZONE_CHOICES,
default='UTC'
)

def __str__(self):
return f"{self.user.username} ({self.timezone})"

Step 2: Activate the User's Timezone with Middleware

Rather than manually activating the timezone in every view, use a middleware to do it automatically for each request:

# middleware.py

import zoneinfo
from django.utils import timezone


class UserTimezoneMiddleware:
def __init__(self, get_response):
self.get_response = get_response

def __call__(self, request):
if request.user.is_authenticated:
try:
user_tz = request.user.profile.timezone
timezone.activate(zoneinfo.ZoneInfo(user_tz))
except Exception:
timezone.deactivate()
else:
timezone.deactivate()

response = self.get_response(request)
return response

Register the middleware in settings.py:

# settings.py

MIDDLEWARE = [
# ... other middleware ...
'yourapp.middleware.UserTimezoneMiddleware',
]

With this middleware in place, all template rendering and localtime() calls will automatically use the logged-in user's timezone.

Step 3: Display Localized Times in Templates

Django templates automatically convert datetime values to the active timezone when USE_TZ = True. You can also use the {% timezone %} template tag for explicit control:

{% load tz %}

<!-- Uses the currently active timezone (set by middleware) -->
<p>Event starts at: {{ event.start_time }}</p>

<!-- Explicitly render in a specific timezone -->
{% timezone "Asia/Tokyo" %}
<p>Event starts at (Tokyo): {{ event.start_time }}</p>
{% endtimezone %}

Automatically Detecting the User's Timezone

Instead of asking users to manually select a timezone, you can detect it automatically using JavaScript and send it to the server.

Client-Side Detection

<form method="post" action="/update-timezone/">
{% csrf_token %}
<input type="hidden" id="timezone-input" name="timezone" value="">
<button type="submit" id="tz-submit" style="display:none;">Submit</button>
</form>

<script>
document.addEventListener('DOMContentLoaded', function() {
var tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
document.getElementById('timezone-input').value = tz;
// Optionally auto-submit or store in a cookie/session
});
</script>

Server-Side View

from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required


@login_required
def update_timezone(request):
if request.method == 'POST':
user_timezone = request.POST.get('timezone', 'UTC')
profile = request.user.profile
profile.timezone = user_timezone
profile.save()
return redirect('home')
tip

The Intl.DateTimeFormat().resolvedOptions().timeZone API is supported in all modern browsers and returns IANA timezone strings like "America/Chicago", which are fully compatible with Django and Python's zoneinfo module.

Summary

Setting / FunctionPurpose
TIME_ZONE in settings.pySets the project's default timezone
USE_TZ = TrueEnables timezone-aware storage and conversion
timezone.now()Returns the current UTC time as a timezone-aware object
localtime(dt)Converts a datetime to the currently active timezone
timezone.activate(tz)Sets the active timezone for the current thread/request
zoneinfo.ZoneInfo('...')Creates a timezone object from an IANA timezone name

By configuring your default timezone, enabling USE_TZ, and implementing user-specific timezone support through middleware, your Django application will handle time-related data accurately regardless of where your users are located.