Printing Datetimes in Python
Printing datetime objects clearly and consistently is essential for logging, debugging, reports, dashboards, and API responses. In data science, you need both machine-readable formats (for storage and APIs) and human-readable formats (for logs and reports). Python gives you several clean ways to control exactly how datetimes appear when printed.
TL;DR — Recommended Printing Methods
print(dt)orstr(dt)→ default ISO-like formatdt.strftime(...)→ full control over formatdt.isoformat()→ standard machine-readable output- pandas
.dt.strftime()→ vectorized printing for DataFrames
1. Basic Printing of Datetimes
from datetime import datetime
from zoneinfo import ZoneInfo
now = datetime.now(ZoneInfo("UTC"))
print(now) # Default: 2026-03-19 14:30:25.123456+00:00
print(str(now)) # Same as above
print(now.isoformat()) # Clean ISO 8601: 2026-03-19T14:30:25.123456+00:00
2. Custom Formatting with strftime()
print(now.strftime("%Y-%m-%d %H:%M:%S")) # 2026-03-19 14:30:25
print(now.strftime("%A, %B %d, %Y at %I:%M %p")) # Thursday, March 19, 2026 at 02:30 PM
print(now.strftime("%d/%m/%Y %H:%M")) # 19/03/2026 14:30
3. Real-World Data Science Examples
import pandas as pd
# Create a small demo file so this example runs as-is
# (in your project, sales_data.csv is your real export)
import numpy as np
rng = np.random.default_rng(42)
n = 60
pd.DataFrame({
"order_id": range(1001, 1001 + n),
"order_date": pd.date_range("2026-01-01", periods=n, freq="3D"),
"customer_id": rng.integers(101, 121, n),
"customer_name": rng.choice([" ana", "ben ", "chen", "dana"], n),
"product_id": rng.integers(1, 9, n),
"region": rng.choice(["North", "South", "East", "West"], n),
"category": rng.choice(["Electronics", "Computers", "Books", "Home"], n),
"payment_method": rng.choice(["card", "cash", "wallet"], n),
"segment": rng.choice(["consumer", "business"], n),
"quantity": rng.integers(1, 6, n),
"amount": rng.uniform(50, 2500, n).round(2),
"discount": rng.choice([0.0, 0.05, 0.1, 0.2], n),
}).assign(
price=lambda d: (d["amount"] / d["quantity"]).round(2),
profit=lambda d: (d["amount"] * rng.uniform(0.05, 0.3, n)).round(2),
).assign(
ship_date=lambda d: d["order_date"] + pd.Timedelta(days=2),
status=lambda d: np.where(d["amount"] > 2000, "priority", "standard"),
).to_csv("sales_data.csv", index=False)
df = pd.read_csv("sales_data.csv", parse_dates=["order_date"])
# Add nicely formatted columns for reports
df["order_date_human"] = df["order_date"].dt.strftime("%A, %B %d, %Y")
df["order_time_human"] = df["order_date"].dt.strftime("%I:%M %p")
# For logging
for row in df.itertuples():
print(f"Order at {row.order_date.strftime('%Y-%m-%d %H:%M:%S')} by customer {row.customer_id}")
4. Best Practices in 2026
- Use
strftime()for human-readable output in logs and reports - Use
isoformat()for machine-readable output (APIs, JSON, storage) - Always print timezone-aware datetimes with their offset
- Use pandas
.dt.strftime()for bulk formatting in DataFrames - Define common format strings as constants for consistency across your project
Printing for People and Machines
print(dt) shows str(dt), a readable ISO-like form, while repr(dt) shows the constructor call used for debugging. f-strings accept format codes directly, as in f"{dt:%Y-%m-%d %H:%M}".
For logs and data files, ISO format with an offset is best, because it is unambiguous. For reports, choose a friendly format and stay consistent across the document.
Avoid printing microseconds in reports; trim them with timespec in isoformat or with a shorter strftime format.
Worked Example: str, repr and f-string Formats
One datetime is printed in several ways.
from datetime import datetime, timezone
dt = datetime(2026, 3, 19, 14, 30, 5, 123456, tzinfo=timezone.utc)
print(str(dt))
print(repr(dt))
print(f"{dt:%d %b %Y, %H:%M}")
print(dt.isoformat(timespec="seconds"))
print(f"Report generated {dt:%A} at {dt:%H:%M} UTC")
str includes microseconds and the offset, repr shows the full constructor call, the f-string gives a compact report label, and isoformat with timespec="seconds" trims the microseconds.
Practical Tips
Logging handlers can format timestamps for you. Setting a formatter with datefmt="%Y-%m-%dT%H:%M:%S%z" keeps every log line in the same unambiguous format.
For dashboards and charts, shorter labels such as "19 Mar" are easier to read, while the full timestamp can appear in a tooltip or table.
Avoid formats that depend on the machine's locale, such as %c or %x, in files other systems will read, because the result changes between computers.
Choose one convention per project and apply it everywhere, from logs to exports.
Common Mistakes
- Printing raw repr values in reports.
- Showing microseconds to end users.
- Omitting the time zone in logs.
- Using different formats across one report.
Quick Summary
- str is readable, repr is for debugging.
- f-strings accept format codes.
- timespec trims precision.
- Be consistent within a report.
Conclusion
Printing datetimes effectively is a small but important skill that improves the readability of logs, reports, and dashboards. In 2026, combine strftime() for beautiful human-readable output and isoformat() for clean machine-readable output. These techniques make your data science code more professional and easier to work with for both humans and machines.
Next steps:
- Add formatted datetime columns to your current datasets using
strftime()for better reporting and logging