Printing Datetimes in Python

Dates And Time Mar 19, 2026

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) or str(dt) → default ISO-like format
  • dt.strftime(...) → full control over format
  • dt.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

Related Tutorials

Share:
Last updated: March 2026
Built-in Functions in Python 2026 str() in Python 2026: String Conversion + Modern Formatting & Best Practices memoryview with JAX in Python 2026: Zero-Copy NumPy → JAX Array Interop + Efficient ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + GPU Pinning & ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + ML Examples memoryview with NumPy & PyTorch in Python 2026: Zero-Copy Views, Efficient Slicing & ML Interop Examples memoryview with NumPy in Python 2026: Zero-Copy Views, Efficient Slicing & Real ML Examples memoryview() in Python 2026: Zero-Copy Magic for Large Binary Data + Real Examples import() in Python 2026: How It Works, Security Risks & Modern Alternatives (importlib) zip() in Python 2026: How to Use It, strict=True Behavior & Real-World Examples vars() in Python 2026: Accessing Object Namespace + Modern Introspection Patterns type() in Python 2026: Dynamic Type Inspection & Object Creation + Modern Patterns tuple() in Python 2026: Immutable Sequences + Modern Patterns & Best Practices super() in Python 2026: Method Resolution & Modern Inheritance Patterns sum() in Python 2026: Summing Iterables + Modern Numeric Patterns & Best Practices staticmethod() in Python 2026: Static Methods, Utility Functions & Modern Best Practices sorted() in Python 2026: Sorting Iterables + Modern Patterns & Best Practices slice() in Python 2026: Creating Slice Objects + Modern Patterns & Best Practices setattr() in Python 2026: Dynamic Attribute Setting + Modern Patterns & Safety set() in Python 2026: Mutable Sets Creation + Modern Patterns & Best Practices