To convert a datetime to a string in Python, call strftime() with a format: dt.strftime("%Y-%m-%d %H:%M:%S"). Use dt.isoformat() for ISO 8601 strings (APIs, JSON), str(dt) for a quick default, or a format spec inside an f-string. In Django, convert aware datetimes to local time with timezone.localtime() first, and format them in templates with the date filter. This guide covers all of these, with time zones, timestamps, pandas columns and the two most common errors.
All examples were run with Python 3.12.5, Django 6.1.1 and pandas 3.0.6; the screenshots show the real output in the Windows Command Prompt. The full list of format codes is in the Python docs under strftime() and strptime() format codes; Django’s letters are in the date template filter reference.
Convert datetime to string in Python
from datetime import datetime
order_time = datetime(2025, 7, 4, 14, 30, 5)
print(order_time.strftime("%Y-%m-%d %H:%M:%S")) # custom format
print(str(order_time)) # default string
print(order_time.isoformat()) # ISO 8601 for APIs and JSON
print(f"Order placed on {order_time:%B %d, %Y at %I:%M %p}") # format inside an f-string
Output:
2025-07-04 14:30:05
2025-07-04 14:30:05
2025-07-04T14:30:05
Order placed on July 04, 2025 at 02:30 PM
| Method | Result for 4 July 2025, 14:30:05 | Use it for |
|---|---|---|
dt.strftime("%Y-%m-%d %H:%M:%S") | 2025-07-04 14:30:05 | Any custom format |
str(dt) | 2025-07-04 14:30:05 | Quick debugging output |
dt.isoformat() | 2025-07-04T14:30:05 | APIs, JSON, databases |
f"{dt:%d/%m/%Y}" | 04/07/2025 | Formatting inside a longer string |
strftime format codes (yyyy-mm-dd, yyyymmdd and more)
Each % code is replaced by part of the date. These are the formats people ask for most often:
from datetime import datetime
dt = datetime(2025, 7, 4, 14, 30, 5)
formats = {
"%Y-%m-%d": "ISO date (yyyy-mm-dd)",
"%Y%m%d": "compact (yyyymmdd)",
"%m/%d/%Y": "US date",
"%d/%m/%Y": "UK / India date",
"%d-%b-%Y": "day-month name-year",
"%A, %B %d, %Y": "long date",
"%I:%M %p": "12-hour time",
"%H:%M:%S": "24-hour time",
"%Y-%m-%dT%H:%M:%S": "ISO date and time",
"%Y%m%d_%H%M%S": "file name friendly",
}
for code, meaning in formats.items():
print(f"{code:<20} {dt.strftime(code):<28} {meaning}")
Output:
%Y-%m-%d 2025-07-04 ISO date (yyyy-mm-dd)
%Y%m%d 20250704 compact (yyyymmdd)
%m/%d/%Y 07/04/2025 US date
%d/%m/%Y 04/07/2025 UK / India date
%d-%b-%Y 04-Jul-2025 day-month name-year
%A, %B %d, %Y Friday, July 04, 2025 long date
%I:%M %p 02:30 PM 12-hour time
%H:%M:%S 14:30:05 24-hour time
%Y-%m-%dT%H:%M:%S 2025-07-04T14:30:05 ISO date and time
%Y%m%d_%H%M%S 20250704_143005 file name friendly
| Code | Meaning | Example |
|---|---|---|
%Y / %y | Year with / without century | 2025 / 25 |
%m / %B / %b | Month number / full name / short name | 07 / July / Jul |
%d | Day of the month | 04 |
%A / %a | Weekday name / short name | Friday / Fri |
%H / %I | Hour (24-hour) / hour (12-hour) | 14 / 02 |
%M / %S | Minutes / seconds | 30 / 05 |
%p | AM or PM | PM |
%z / %Z | UTC offset / time zone name | -0400 / EDT |
%f | Microseconds | 000000 |
Month and day names follow the current locale. %-d (day without a leading zero) works on Linux and macOS but not on Windows, where you can use f"{dt.day}" instead.
Date, time and datetime.now() to string
from datetime import date, datetime, time
print(date(2025, 12, 25).strftime("%d %B %Y")) # a date object
print(time(9, 5).strftime("%H:%M")) # a time object
print(datetime.now().strftime("%Y-%m-%d %H:%M")) # current date and time (changes every run)
print(date.today().isoformat()) # today as yyyy-mm-dd
Output (the third line shows the time of the run):
25 December 2025
09:05
2026-09-22 13:08
2026-09-22
Datetime to string with a time zone
Use aware datetimes (with tzinfo) from the standard zoneinfo module. %Z and %z add the zone name and offset, isoformat() includes the offset automatically, and astimezone() converts before formatting:
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
meeting = datetime(2025, 11, 3, 9, 0, tzinfo=ZoneInfo("America/New_York"))
print(meeting.strftime("%Y-%m-%d %H:%M %Z (UTC%z)")) # with time zone name and offset
print(meeting.isoformat()) # offset included automatically
print(meeting.astimezone(ZoneInfo("Asia/Kolkata")).strftime("%Y-%m-%d %H:%M %Z"))
print(meeting.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")) # UTC string for APIs
Output:
2025-11-03 09:00 EST (UTC-0500)
2025-11-03T09:00:00-05:00
2025-11-03 19:30 IST
2025-11-03T14:00:00Z
On Windows, zoneinfo needs the tzdata package (pip install tzdata); it is installed automatically with pandas and Django.
Timestamp to string
Unix timestamps are seconds since 1 January 1970 UTC. Convert them with datetime.fromtimestamp() and pass tz so the result does not depend on the computer’s time zone:
from datetime import datetime, timezone
ts = 1751639405 # Unix timestamp (seconds since 1970-01-01 UTC)
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
print(dt.strftime("%Y-%m-%d %H:%M:%S %Z"))
ms = 1751639405123 # JavaScript-style milliseconds
print(datetime.fromtimestamp(ms / 1000, tz=timezone.utc).isoformat(timespec="milliseconds"))
Output:
2025-07-04 14:30:05 UTC
2025-07-04T14:30:05.123+00:00
pandas: convert a datetime column to string
For a whole column use the .dt.strftime() accessor; the result is a column of strings (str dtype in pandas 3, object in older versions):
import pandas as pd
df = pd.DataFrame({"order_id": [101, 102, 103],
"created": pd.to_datetime(["2025-07-04 14:30", "2025-07-05 09:15", "2025-07-06 18:45"])})
df["created_str"] = df["created"].dt.strftime("%d/%m/%Y %H:%M") # whole column at once
df["day"] = df["created"].dt.strftime("%A")
print(df)
print(df.dtypes)
Output:
order_id created created_str day
0 101 2025-07-04 14:30:00 04/07/2025 14:30 Friday
1 102 2025-07-05 09:15:00 05/07/2025 09:15 Saturday
2 103 2025-07-06 18:45:00 06/07/2025 18:45 Sunday
order_id int64
created datetime64[us]
created_str str
day str
dtype: object
To go the other way, see convert a string to datetime in pandas.
Convert datetime to string in Django
With USE_TZ = True (the default for new projects) Django stores datetimes in UTC. If you call strftime() on a model field directly, you get UTC time. Convert to the project’s TIME_ZONE with timezone.localtime() first. In templates, the date filter does the conversion and formatting for you. This standalone script runs the same code you would use in a view:
import django
from django.conf import settings
settings.configure(USE_TZ=True, TIME_ZONE="America/New_York",
TEMPLATES=[{"BACKEND": "django.template.backends.django.DjangoTemplates"}])
django.setup()
from datetime import datetime, timezone as dt_timezone
from django.template import Context, Template
from django.utils import timezone
from django.utils.dateformat import format as date_format
created = datetime(2025, 7, 4, 18, 30, tzinfo=dt_timezone.utc) # stored in UTC, as Django does
local = timezone.localtime(created) # convert to TIME_ZONE
print("Python strftime :", local.strftime("%Y-%m-%d %H:%M %Z"))
print("Django format() :", date_format(local, "D, d M Y, P")) # Django's own format letters
template = Template('{{ created|date:"Y-m-d H:i" }} | {{ created|date:"N j, Y, P" }} | {{ created|date:"c" }}')
print("Template filter :", template.render(Context({"created": created})))
Output:
Python strftime : 2025-07-04 14:30 EDT
Django format() : Fri, 04 Jul 2025, 2:30 p.m.
Template filter : 2025-07-04 14:30 | July 4, 2025, 2:30 p.m. | 2025-07-04T14:30:00-04:00
localtime(), dateformat.format() and the date template filter.In a real template you only write the filter:
<p>Ordered on {{ order.created|date:"d M Y, H:i" }}</p>
<time datetime="{{ order.created|date:'c' }}">{{ order.created|date:"N j, Y" }}</time>
Django’s filter letters differ from Python’s % codes: Y-m-d H:i in a template equals %Y-%m-%d %H:%M in Python. The filter without an argument ({{ value|date }}) uses the DATE_FORMAT setting, but with localization active the current language’s format takes precedence, so pass an explicit format when it must look the same everywhere. For JSON responses, JsonResponse uses DjangoJSONEncoder, which turns datetimes into ISO 8601 strings.
Common errors
from datetime import datetime
dt = datetime(2025, 7, 4, 14, 30)
try:
message = "Created: " + dt # str + datetime
except TypeError as e:
print("TypeError:", e)
value = "2025-07-04 14:30" # already a string
try:
value.strftime("%d/%m/%Y")
except AttributeError as e:
print("AttributeError:", e)
print("Created: " + dt.strftime("%Y-%m-%d")) # fix: convert first
Output:
TypeError: can only concatenate str (not "datetime.datetime") to str
AttributeError: 'str' object has no attribute 'strftime'
Created: 2025-07-04
strftime() on a string both fail.- TypeError: can only concatenate str (not “datetime.datetime”) to str: convert first with
strftime(), or use an f-string. - AttributeError: ‘str’ object has no attribute ‘strftime’: the value is already a string. Parse it with
datetime.strptime()first if you need a different format.
Related Python date and time guides:
- Convert a string to datetime in Python
- Convert a string column to datetime in pandas
- Format dates in Django templates
Frequently asked questions
How do I convert a datetime to a string in Python?
Use strftime(): dt.strftime("%Y-%m-%d %H:%M:%S"). For ISO 8601, use dt.isoformat().
How do I convert a date to a yyyy-mm-dd string?
d.strftime("%Y-%m-%d") or simply d.isoformat() for a date object.
How do I convert datetime.now() to a string?
datetime.now().strftime("%Y-%m-%d %H:%M:%S"). Pass a time zone, for example datetime.now(ZoneInfo("UTC")), if the string must not depend on the server’s zone.
How do I convert a datetime to a string in Django?
In Python code, use timezone.localtime(value).strftime(...). In templates, use the date filter: {{ value|date:"Y-m-d H:i" }}.
How do I include the time zone in the string?
Use an aware datetime and add %Z (name) or %z (offset) to the format, or use isoformat(), which includes the offset.
How do I convert a pandas datetime column to string?
df["col"].dt.strftime("%Y-%m-%d") converts every value in the column.
Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn