
Python Course
Date & Time in Python
Dates and times appear in almost every real application — order timestamps, user activity logs, scheduled tasks, billing cycles, and data exports all depend on accurate time handling. Python's built-in datetime module gives you everything you need to create, format, parse, compare, and do arithmetic with dates and times — no third-party packages required.
This lesson covers all four core classes, formatting and parsing, timedelta arithmetic, comparison, timezones, timestamp conversion, and a real-world scheduling example.
The Four Core Classes
date— stores a calendar date: year, month, day onlytime— stores a time of day: hour, minute, second, microsecond onlydatetime— stores both date and time combined — the most commonly used classtimedelta— represents a duration or difference between two points in time
from datetime import date, time, datetime, timedelta
# date — year, month, day
d = date(2024, 7, 19)
print(d) # 2024-07-19
print(d.year, d.month, d.day) # 2024 7 19
# time — hour, minute, second, microsecond
t = time(14, 30, 0)
print(t) # 14:30:00
# datetime — date AND time combined
dt = datetime(2024, 7, 19, 14, 30, 0)
print(dt) # 2024-07-19 14:30:00
# timedelta — a duration
delta = timedelta(days=7, hours=3, minutes=30)
print(delta) # 7 days, 3:30:00
# datetime.combine — merge separate date and time objects
combined = datetime.combine(d, t)
print(combined) # 2024-07-19 14:30:00- Import from
datetime— the module and the main class share the same name, sofrom datetime import datetimeis the standard pattern. - Month and day are 1-indexed — January is 1, not 0. Hours use 24-hour format.
datetime.combine(date, time)merges adateand atimeinto adatetime.
Getting the Current Date and Time
from datetime import date, datetime
today = date.today()
print("Today :", today)
now = datetime.now()
print("Now :", now)
# Access individual components
print("Year :", now.year)
print("Month :", now.month)
print("Day :", now.day)
print("Hour :", now.hour)
print("Minute :", now.minute)
print("Second :", now.second)
# weekday() — Monday=0, Sunday=6
# isoweekday() — Monday=1, Sunday=7
print("weekday() :", now.weekday())
print("Day name :", now.strftime("%A"))
# UTC timestamp (preferred for storing in databases)
from datetime import timezone
utc_now = datetime.now(tz=timezone.utc)
print("UTC now :", utc_now)date.today()returns today's date with no time component.datetime.now()returns current local date and time including microseconds.datetime.now(tz=timezone.utc)returns an aware UTC datetime — preferred for database timestamps.weekday()returns 0 for Monday through 6 for Sunday.
Formatting Dates — strftime()
strftime() converts a date or datetime object into a formatted string. The % format codes control the output. Use it for filenames, receipts, UI display, and export files.
from datetime import datetime
dt = datetime(2024, 7, 19, 14, 30, 5)
# Common patterns
print(dt.strftime("%Y-%m-%d")) # 2024-07-19 ISO 8601
print(dt.strftime("%m/%d/%Y")) # 07/19/2024 US style
print(dt.strftime("%d/%m/%Y")) # 19/07/2024 European style
print(dt.strftime("%d-%b-%Y")) # 19-Jul-2024
print(dt.strftime("%B %d, %Y")) # July 19, 2024
print(dt.strftime("%I:%M %p")) # 02:30 PM 12-hour clock
print(dt.strftime("%H:%M:%S")) # 14:30:05 24-hour clock
print(dt.strftime("%A, %B %d, %Y")) # Friday, July 19, 2024
# Practical: timestamped filename
filename = dt.strftime("report_%Y%m%d_%H%M%S.csv")
print(filename) # report_20240719_143005.csv
# ISO 8601 with time — standard for APIs and databases
print(dt.isoformat()) # 2024-07-19T14:30:05| Code | Meaning | Example |
|---|---|---|
%Y | 4-digit year | 2024 |
%m | Zero-padded month | 07 |
%d | Zero-padded day | 19 |
%H | 24-hour hour | 14 |
%I | 12-hour hour | 02 |
%M | Minutes | 30 |
%S | Seconds | 05 |
%A | Full weekday name | Friday |
%B | Full month name | July |
%b | Abbreviated month | Jul |
%p | AM/PM | PM |
Parsing Strings into Dates — strptime()
strptime() does the reverse of strftime() — it parses a date string and converts it into a datetime object. Use it whenever dates arrive as strings from CSV files, APIs, or user input.
from datetime import datetime
# Format must match the input string exactly
dt1 = datetime.strptime("2024-07-19", "%Y-%m-%d")
print(dt1) # 2024-07-19 00:00:00
dt2 = datetime.strptime("07/19/2024 02:30 PM", "%m/%d/%Y %I:%M %p")
print(dt2) # 2024-07-19 14:30:00
dt3 = datetime.strptime("19-Jul-2024", "%d-%b-%Y")
print(dt3) # 2024-07-19 00:00:00
# Parse date part only
print(dt1.date()) # 2024-07-19
# Sort a list of date strings by parsing them first
date_strings = ["2024-03-15", "2024-01-02", "2024-06-30", "2024-01-01"]
parsed = [datetime.strptime(d, "%Y-%m-%d") for d in date_strings]
sorted_dates = [d.strftime("%Y-%m-%d") for d in sorted(parsed)]
print(sorted_dates)
# Error handling — wrong format raises ValueError
try:
datetime.strptime("19/07/2024", "%Y-%m-%d")
except ValueError as e:
print("Parse error:", e)Date Arithmetic with timedelta
A timedelta represents a span of time. Add or subtract timedeltas to calculate future or past moments. Subtracting two dates gives a timedelta.
from datetime import date, datetime, timedelta
today = date(2024, 7, 19)
# Add and subtract
next_week = today + timedelta(days=7)
in_30_days = today + timedelta(days=30)
last_week = today - timedelta(days=7)
print("Next week :", next_week)
print("In 30 days:", in_30_days)
print("Last week :", last_week)
# Difference between two dates → timedelta
start = date(2024, 1, 1)
gap = today - start
print("Days since Jan 1:", gap.days)
print("Weeks since Jan 1:", gap.days // 7)
# timedelta with hours and minutes
deadline = datetime(2024, 7, 19, 9, 0, 0)
extended = deadline + timedelta(hours=2, minutes=30)
print("Extended deadline:", extended)
# total_seconds() — convert any duration to seconds
duration = timedelta(days=1, hours=6, minutes=30)
print("Total seconds:", duration.total_seconds())
print("Total hours :", duration.total_seconds() / 3600)
# Check if something happened within the last 7 days
event_date = date(2024, 7, 15)
if (today - event_date).days <= 7:
print("Event was within the last week")timedeltaaccepts:days,seconds,microseconds,milliseconds,minutes,hours,weeks.- Use
.total_seconds()rather than.seconds—.secondsonly gives the seconds component, ignoring days.
Comparing Dates and Datetimes
Date and datetime objects support all standard comparison operators: <, >, ==, !=, <=, >=. This makes filtering and deadline checking straightforward.
from datetime import date, datetime
d1 = date(2024, 1, 1)
d2 = date(2024, 7, 19)
print(d1 < d2) # True — d1 is earlier
print(d1 == d2) # False
print(max(d1, d2)) # 2024-07-19
# Practical: check subscription expiry
today = date(2024, 7, 19)
expiry = date(2025, 12, 31)
days_left = (expiry - today).days
if expiry > today:
print(f"Active — {days_left} days remaining")
else:
print("Subscription expired")
# Sort a list of datetimes
events = [
datetime(2024, 3, 15, 9, 0),
datetime(2024, 1, 2, 14, 30),
datetime(2024, 6, 30, 8, 0),
]
for e in sorted(events):
print(e.strftime(" %B %d, %Y at %I:%M %p"))Working with Timezones
A naive datetime has no timezone info. An aware datetime knows its timezone. Always use aware datetimes for any application with multiple users, multiple locations, or database storage.
from datetime import datetime
from zoneinfo import ZoneInfo # Python 3.9+ built-in
# Create an aware datetime in UTC
utc_now = datetime.now(tz=ZoneInfo("UTC"))
print("UTC :", utc_now.strftime("%Y-%m-%d %H:%M %Z"))
# Convert to different timezones
eastern = utc_now.astimezone(ZoneInfo("America/New_York"))
pacific = utc_now.astimezone(ZoneInfo("America/Los_Angeles"))
london = utc_now.astimezone(ZoneInfo("Europe/London"))
tokyo = utc_now.astimezone(ZoneInfo("Asia/Tokyo"))
print("New York:", eastern.strftime("%Y-%m-%d %H:%M %Z"))
print("Pacific :", pacific.strftime("%Y-%m-%d %H:%M %Z"))
print("London :", london.strftime("%Y-%m-%d %H:%M %Z"))
print("Tokyo :", tokyo.strftime("%Y-%m-%d %H:%M %Z"))
# Attach timezone to a specific datetime
meeting = datetime(2024, 7, 19, 10, 0, tzinfo=ZoneInfo("America/New_York"))
print("Meeting (NY) :", meeting.strftime("%H:%M %Z"))
print("Meeting (UTC) :", meeting.astimezone(ZoneInfo("UTC")).strftime("%H:%M %Z"))zoneinfois built into Python 3.9+ — no installation needed. For Python 3.8 and below, use thepytzlibrary..astimezone(tz)converts an aware datetime to any other timezone.- Best practice: store all timestamps in UTC, convert to local timezone only for display.
Unix Timestamps
Many systems (databases, APIs, JavaScript) represent time as a Unix timestamp — the number of seconds since January 1, 1970 UTC. Python converts easily in both directions.
from datetime import datetime, timezone
# datetime → Unix timestamp
dt = datetime(2024, 7, 19, 14, 30, 0, tzinfo=timezone.utc)
ts = dt.timestamp()
print("Timestamp:", ts) # 1721396200.0
# Unix timestamp → datetime
from datetime import datetime, timezone
back = datetime.fromtimestamp(ts, tz=timezone.utc)
print("Back to datetime:", back.strftime("%Y-%m-%d %H:%M:%S %Z"))
# Current time as Unix timestamp
now_ts = datetime.now(tz=timezone.utc).timestamp()
print("Now (Unix):", int(now_ts))Real-World Example — Subscription Manager
from datetime import date, timedelta
def subscription_report(users):
today = date.today()
# Use a fixed date for consistent example output
today = date(2024, 7, 19)
print(f"{'Name':<12} {'Expiry':<14} {'Status':<12} {'Days Left'}")
print("-" * 52)
for user in sorted(users, key=lambda u: u["expiry"]):
expiry = user["expiry"]
days_left = (expiry - today).days
if days_left < 0:
status = "EXPIRED"
elif days_left <= 7:
status = "EXPIRING SOON"
else:
status = "Active"
print(f"{user['name']:<12} {expiry.strftime('%Y-%m-%d'):<14} {status:<14} {days_left:>4}")
users = [
{"name": "Alice", "expiry": date(2024, 7, 15)}, # expired
{"name": "Bob", "expiry": date(2024, 7, 22)}, # expiring soon
{"name": "Carol", "expiry": date(2024, 8, 1)}, # active
{"name": "Dave", "expiry": date(2025, 1, 1)}, # active
{"name": "Eve", "expiry": date(2024, 7, 19)}, # expires today
]
subscription_report(users)
# Calculate renewal dates (30-day extension from today)
print()
today = date(2024, 7, 19)
for user in users:
if (user["expiry"] - today).days <= 7:
renewal = today + timedelta(days=30)
print(f" {user['name']}: renewal would be {renewal.strftime('%B %d, %Y')}")Quick Reference Table
| Tool | Purpose | Key Usage |
|---|---|---|
date | Calendar date only | date.today() |
datetime | Date and time combined | datetime.now() |
timedelta | Duration / date arithmetic | timedelta(days=n) |
strftime() | datetime → formatted string | dt.strftime("%Y-%m-%d") |
strptime() | String → datetime | datetime.strptime(s, fmt) |
isoformat() | datetime → ISO 8601 string | dt.isoformat() |
timestamp() | datetime → Unix timestamp | dt.timestamp() |
ZoneInfo | Timezone-aware datetimes | datetime.now(tz=ZoneInfo("UTC")) |
total_seconds() | timedelta → float in seconds | delta.total_seconds() |
Practice
Which class stores only a calendar date with no time component?
What method converts a datetime object into a formatted string?
What type is returned when you subtract two date objects?
What format code produces a four-digit year in strftime()?
What is the difference between a naive and an aware datetime?
Which timedelta method gives the full duration as a single float in seconds?
Quick Quiz
What does date.today() return?
What does datetime.strptime("2024-07-19", "%Y-%m-%d") return?
Which timedelta attribute gives the total duration as a single float in seconds?
What integer does weekday() return for Monday?
Which module built into Python 3.9+ handles timezone-aware datetimes?
What is the best practice for handling timestamps in a global application?