How to Convert Datetime to String in Python and Django

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
Command Prompt output converting a Python datetime to a string with strftime, str(), isoformat() and an f-string
Four ways to turn the same datetime into text.
MethodResult for 4 July 2025, 14:30:05Use it for
dt.strftime("%Y-%m-%d %H:%M:%S")2025-07-04 14:30:05Any custom format
str(dt)2025-07-04 14:30:05Quick debugging output
dt.isoformat()2025-07-04T14:30:05APIs, JSON, databases
f"{dt:%d/%m/%Y}"04/07/2025Formatting 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
Command Prompt table of Python strftime format codes with their output, including yyyy-mm-dd, yyyymmdd, US and UK dates, 12-hour and 24-hour time
Common strftime formats and their output.
CodeMeaningExample
%Y / %yYear with / without century2025 / 25
%m / %B / %bMonth number / full name / short name07 / July / Jul
%dDay of the month04
%A / %aWeekday name / short nameFriday / Fri
%H / %IHour (24-hour) / hour (12-hour)14 / 02
%M / %SMinutes / seconds30 / 05
%pAM or PMPM
%z / %ZUTC offset / time zone name-0400 / EDT
%fMicroseconds000000

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
Command Prompt output of a Python datetime in America/New_York converted to strings with %Z and %z, isoformat, Asia/Kolkata time and UTC
The same meeting as New York, India and UTC strings.

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
Command Prompt output of Django converting a UTC datetime to America/New_York and formatting it with strftime, dateformat.format and the date template filter
Django’s 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
Command Prompt showing TypeError can only concatenate str (not datetime.datetime) to str and AttributeError str object has no attribute strftime
Concatenating a datetime and calling 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:

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.