Skip to content
Home Python datetime Module in Python

datetime Module in Python

Where developers are forged. · Structured learning · Free forever.
📍 Part of: Python Libraries → Topic 13 of 51
Python datetime module — creating dates and times, formatting with strftime, parsing with strptime, timedelta arithmetic, timezone handling, and the common pitfalls.
🧑‍💻 Beginner-friendly — no prior Python experience needed
In this tutorial, you'll learn
Python datetime module — creating dates and times, formatting with strftime, parsing with strptime, timedelta arithmetic, timezone handling, and the common pitfalls.
  • Use datetime.now(timezone.utc) for the current UTC time — always timezone-aware.
  • strftime formats a datetime as a string. strptime parses a string into a datetime.
  • timedelta represents a duration — use it for date arithmetic.
✦ Plain-English analogy ✦ Real code with output ✦ Interview questions
Quick Answer

Python's datetime module has four main classes: date (year/month/day), time (hour/minute/second), datetime (both), and timedelta (a duration). Use datetime.now() for the current local time, datetime.utcnow() for UTC, and always use timezone-aware datetimes in production to avoid ambiguity across timezones.

Creating and Formatting Dates

Example · PYTHON
1234567891011121314151617181920212223
from datetime import date, time, datetime, timedelta

# Current date and time
today     = date.today()
now       = datetime.now()  # local time, naive (no timezone)

print(today)          # 2026-03-17
print(now)            # 2026-03-17 11:30:45.123456

# Create specific dates
birthday  = date(1990, 6, 15)
meeting   = datetime(2026, 3, 20, 14, 30, 0)

# Format with strftime
print(meeting.strftime('%A, %B %d %Y at %H:%M'))
# Thursday, March 20 2026 at 14:30

print(meeting.strftime('%d/%m/%Y'))  # 20/03/2026
print(meeting.isoformat())           # 2026-03-20T14:30:00

# Parse a string with strptime
parsed = datetime.strptime('20/03/2026 14:30', '%d/%m/%Y %H:%M')
print(parsed)  # 2026-03-20 14:30:00
▶ Output
2026-03-17
2026-03-17 11:30:45.123456
Thursday, March 20 2026 at 14:30
20/03/2026
2026-03-20T14:30:00
2026-03-20 14:30:00

timedelta — Date Arithmetic

Example · PYTHON
1234567891011121314151617181920212223
from datetime import datetime, timedelta

now = datetime(2026, 3, 17, 12, 0, 0)

# Add and subtract durations
tomorrow   = now + timedelta(days=1)
last_week  = now - timedelta(weeks=1)
in_90_days = now + timedelta(days=90)

print(tomorrow)    # 2026-03-18 12:00:00
print(last_week)   # 2026-03-10 12:00:00
print(in_90_days)  # 2026-06-15 12:00:00

# Difference between two datetimes
deadline = datetime(2026, 4, 1, 0, 0, 0)
delta    = deadline - now
print(f"{delta.days} days, {delta.seconds // 3600} hours until deadline")

# Days since epoch — useful for calculations
from datetime import date
today = date.today()
d = today - date(2000, 1, 1)
print(f"Days since Y2K: {d.days}")
▶ Output
2026-03-18 12:00:00
2026-03-10 12:00:00
2026-06-15 12:00:00
14 days, 12 hours until deadline
Days since Y2K: 9572

Timezones — Naive vs Aware

A naive datetime has no timezone information — it is ambiguous. An aware datetime has a timezone attached. Always use aware datetimes when storing, comparing, or transmitting times.

Example · PYTHON
1234567891011121314151617181920212223
from datetime import datetime, timezone, timedelta

# Aware datetime — UTC
utc_now = datetime.now(timezone.utc)
print(utc_now)            # 2026-03-17 11:30:45.123456+00:00
print(utc_now.isoformat()) # 2026-03-17T11:30:45.123456+00:00

# Convert to a different timezone
ut_plus5 = timezone(timedelta(hours=5))
ist_time  = utc_now.astimezone(ut_plus5)
print(ist_time)  # 2026-03-17 16:30:45.123456+05:00

# Python 3.9+ — use zoneinfo for named timezones
from zoneinfo import ZoneInfo
london = utc_now.astimezone(ZoneInfo('Europe/London'))
print(london)  # handles BST/GMT automatically

# Never compare naive and aware datetimes
naive = datetime(2026, 3, 17, 12, 0)
try:
    print(naive < utc_now)
except TypeError as e:
    print(f"Cannot compare: {e}")
▶ Output
2026-03-17 11:30:45+00:00
Cannot compare: can't compare offset-naive and offset-aware datetimes

🎯 Key Takeaways

  • Use datetime.now(timezone.utc) for the current UTC time — always timezone-aware.
  • strftime formats a datetime as a string. strptime parses a string into a datetime.
  • timedelta represents a duration — use it for date arithmetic.
  • Naive datetimes have no timezone; aware datetimes do. Never mix them in comparisons.
  • Python 3.9+ zoneinfo module handles named timezones (Europe/London, US/Eastern) and DST transitions correctly.

Interview Questions on This Topic

  • QWhat is the difference between a naive and an aware datetime in Python?
  • QHow would you convert a datetime from UTC to a local timezone in Python?
  • QWhat does strftime('%Y-%m-%dT%H:%M:%S') produce?

Frequently Asked Questions

What is the difference between datetime.now() and datetime.utcnow()?

datetime.now() returns the current local time as a naive datetime (no timezone info). datetime.utcnow() returns UTC as a naive datetime. Both are naive — they carry no timezone information. The correct approach is datetime.now(timezone.utc) which returns an aware UTC datetime.

How do I get the timestamp (seconds since epoch) from a datetime?

Use datetime_obj.timestamp(). This returns a float representing seconds since the Unix epoch (1970-01-01 00:00:00 UTC). For the reverse: datetime.fromtimestamp(ts, tz=timezone.utc) to convert a timestamp back to an aware datetime.

🔥
Naren Founder & Author

Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.

← Previouscollections Module in PythonNext →regex Module in Python
Forged with 🔥 at TheCodeForge.io — Where Developers Are Forged