datetime Module in Python
- 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.
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
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
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
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}")
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.
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}")
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.
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.