Formatting with strftime and isoformat

datetime · Essentials · 8 min

Logs, file names, reports and APIs all need dates as strings in a specific format.

ISO 8601 is the default machine format: dt.isoformat() gives 2025-03-01T14:30:00, with an offset like +00:00 for aware values. isoformat(sep=" ", timespec="minutes") adjusts it. Prefer ISO for APIs, logs and file names: it's unambiguous and sorts correctly as text.

For human-readable output, dt.strftime(format) uses % codes:

  • %Y 4-digit year, %m month 01-12, %d day 01-31
  • %H hour 00-23, %I hour 01-12 with %p AM/PM, %M minutes, %S seconds, %f microseconds
  • %A/%a weekday name, %B/%b month name
  • %z UTC offset like +0100, %Z zone name
  • %j day of the year, %% a literal percent sign

The same codes work inside f-strings: f"{dt:%Y-%m-%d}".

Names such as %A and %B depend on the current locale, which is "C" (English) unless the program calls locale.setlocale. For user-facing localised dates, a library like Babel is more reliable than switching process-wide locales.

str(dt) equals dt.isoformat(sep=" "). When formatting file names, avoid : (invalid on Windows): use %Y%m%d-%H%M%S.

Example

from datetime import UTC, datetime

dt = datetime(2025, 3, 1, 14, 5, 9, 123456)
print(dt.isoformat())                     # 2025-03-01T14:05:09.123456
print(dt.isoformat(sep=" ", timespec="minutes"))   # 2025-03-01 14:05
print(dt.strftime("%d/%m/%Y %H:%M"))      # 01/03/2025 14:05
print(dt.strftime("%A %d %B %Y, %I:%M %p"))  # Saturday 01 March 2025, 02:05 PM
print(f"report-{dt:%Y%m%d-%H%M%S}.csv")   # report-20250301-140509.csv
print(f"{dt:%j}")                         # 060

aware = dt.replace(tzinfo=UTC, microsecond=0)
print(aware.isoformat())                  # 2025-03-01T14:05:09+00:00
print(aware.strftime("%H:%M %Z (%z)"))    # 14:05 UTC (+0000)

Remember

  • isoformat() is the unambiguous, sortable machine format
  • strftime and f-string specs use the same % codes
  • Month and day names depend on the locale

Watch out for

  • Using %M (minutes) where %m (month) was meant, or vice versa.

Check yourself

  1. Which format string produces '2025-03-01 09:07' for 1 March 2025, 09:07?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior