Date and Time Formatting
To format date and time objects into strings using Django's custom format specifiers, use the utilities provided in django.utils.dateformat. This system uses a syntax inspired by PHP's date() function.
Formatting a Datetime Object
The most common way to format a datetime or date object is using the format() convenience function.
from datetime import datetime
from django.utils.dateformat import format
# Current date and time
now = datetime.now()
# Format: Day of month with suffix, Full Month, Year, 24h Hour:Minutes
# Example Output: "7th October 2023 14:30"
result = format(now, 'jS F Y H:i')
print(result)
Formatting Time-Only Objects
If you are working specifically with datetime.time objects, use the time_format() function.
from datetime import time
from django.utils.dateformat import time_format
t = time(14, 30)
# Format: 12h hour:minutes with a.m./p.m.
# Example Output: "2:30 p.m."
result = time_format(t, 'f a')
print(result)
Using the DateFormat and TimeFormat Classes
For more control, or if you need to perform multiple formatting operations on the same object, you can instantiate DateFormat or TimeFormat directly.
from datetime import datetime
from django.utils.dateformat import DateFormat
d = datetime(2023, 10, 7, 11, 39)
df = DateFormat(d)
# You can call the format method
print(df.format('Y-m-d')) # "2023-10-07"
# Or call individual format character methods directly
print(df.S()) # "rd" (for the 7th)
print(df.L()) # False (not a leap year)
Escaping Literal Characters
If you want to include a character in your format string that is also a format specifier (like 'Y' or 'H'), you must escape it with a backslash.
from datetime import datetime
from django.utils.dateformat import format
my_date = datetime(1979, 7, 8)
# Escaping 'C', 'E', and 'T' to treat them as literals
# Result: "1979 189 CET"
result = format(my_date, r"Y z \C\E\T")
Common Format Specifiers
The following specifiers are implemented in DateFormat and TimeFormat:
| Specifier | Description | Example |
|---|---|---|
Y | 4-digit year | 2023 |
y | 2-digit year | 23 |
F | Full textual month | October |
m | Month with leading zeros | 01 to 12 |
j | Day of month without leading zeros | 1 to 31 |
S | English ordinal suffix for day | st, nd, rd, th |
H | 24-hour hour with leading zeros | 00 to 23 |
i | Minutes with leading zeros | 00 to 59 |
P | Time with 'midnight'/'noon' (Proprietary) | 1:30 p.m., noon |
f | Time with optional minutes (Proprietary) | 1, 1:30 |
c | ISO 8601 format | 2023-10-07T11:39:00 |
r | RFC 5322 formatted date | Sat, 07 Oct 2023 11:39:00 +0000 |
Troubleshooting: Time Specifiers on Date Objects
A common error occurs when trying to use time-related format specifiers (like H, i, s) on a datetime.date object. The Formatter class explicitly prevents this to avoid misleading output.
from datetime import date
from django.utils.dateformat import format
d = date(2023, 10, 7)
# This will raise a TypeError:
# "The format for date objects may not contain time-related format specifiers (found 'H')."
try:
format(d, 'Y-m-d H:i')
except TypeError as e:
print(e)
To fix this, convert your date object to a datetime object before formatting:
from datetime import datetime, date
from django.utils.dateformat import format
d = date(2023, 10, 7)
dt = datetime.combine(d, datetime.min.time())
print(format(dt, 'Y-m-d H:i')) # "2023-10-07 00:00"
Timezone Handling
TimeFormat (and by extension DateFormat) handles timezones based on the object provided:
- If a naive
datetimeis provided, it uses the default timezone (configured viasettings.TIME_ZONE). - If an aware
datetimeis provided, it uses the object's own timezone information. - Timezone specifiers (like
e,O,T,Z) return an empty string if no timezone information is available (e.g., when formatting adateobject).