A date arrives as a string — "2024-01-15". To compare with another date, group by month, or filter by year, you need a datetime object, not a string.
from datetime import datetime
d = datetime.fromisoformat("2024-01-15")
print(d) # 2024-01-15 00:00:00
print(d.year) # 2024
print(d.month) # 1
print(d.day) # 15fromisoformat parses standard ISO 8601 — YYYY-MM-DD, optionally with time. And the result has .year, .month, .day attributes I can read.
Right. ISO 8601 is the date format — 2024-01-15, 2024-01-15T14:30:00, 2024-01-15T14:30:00+05:30. Always use it for storage and exchange.
What about other formats — 01/15/2024, Jan 15 2024?
Use datetime.strptime(string, format_string) — "string parse time." The format string uses %-codes:
datetime.strptime("01/15/2024", "%m/%d/%Y")
datetime.strptime("Jan 15 2024", "%b %d %Y")And strftime is the reverse — "string format time." Object → string.
When in doubt, use fromisoformat?
Always. If you control the format, store ISO. Reach for strptime only when the data comes from somewhere you don't control and they used a different shape.
datetime — the standard date/time modulefrom datetime import datetime, date, timedeltaThree main classes:
| Class | What it represents |
|---|---|
datetime | a moment — date + time |
date | just a calendar day |
timedelta | a duration (e.g., 2 days, 3 hours) |
We focus on datetime.
fromisoformatfrom datetime import datetime
datetime.fromisoformat("2024-01-15")
# datetime.datetime(2024, 1, 15, 0, 0)
datetime.fromisoformat("2024-01-15T14:30:00")
# datetime.datetime(2024, 1, 15, 14, 30)If the string isn't valid ISO, raises ValueError.
strptimedatetime.strptime("01/15/2024", "%m/%d/%Y")
datetime.strptime("Jan 15 2024", "%b %d %Y")
datetime.strptime("2024-01-15 14:30", "%Y-%m-%d %H:%M")Format codes you'll meet most:
| Code | Meaning | Example |
|---|---|---|
%Y | 4-digit year | 2024 |
%m | month (01–12) | 01 |
%d | day (01–31) | 15 |
%H | hour 24-clock | 14 |
%M | minute | 30 |
%S | second | 00 |
%b | abbreviated month name | Jan |
%B | full month name | January |
%a | abbreviated weekday | Mon |
%A | full weekday | Monday |
strftimed = datetime(2024, 1, 15)
d.strftime("%Y-%m-%d") # '2024-01-15'
d.strftime("%B %d, %Y") # 'January 15, 2024'
d.strftime("%Y-%m") # '2024-01' — useful for groupingd = datetime.fromisoformat("2024-01-15T14:30:00")
d.year # 2024
d.month # 1
d.day # 15
d.hour # 14
d.minute # 30
d.weekday() # 0=Monday, 6=Sundaya = datetime.fromisoformat("2024-01-01")
b = datetime.fromisoformat("2024-06-01")
a < b # True
b - a # datetime.timedelta(days=152)
(b - a).days # 152datetime.now() # current local datetime
date.today() # today's date (no time)fromisoformat is strict. "2024-1-15" (no zero-pad) doesn't parse — must be "2024-01-15". Use strptime if you have unpadded numbers.strptime and strftime have opposite directions. "p for parse, f for format." Easy to confuse.datetime without tzinfo is naive — it has no timezone. For a v1 script that doesn't cross zones, naive is fine. Cross-zone work needs pytz or zoneinfo (deferred).A date arrives as a string — "2024-01-15". To compare with another date, group by month, or filter by year, you need a datetime object, not a string.
from datetime import datetime
d = datetime.fromisoformat("2024-01-15")
print(d) # 2024-01-15 00:00:00
print(d.year) # 2024
print(d.month) # 1
print(d.day) # 15fromisoformat parses standard ISO 8601 — YYYY-MM-DD, optionally with time. And the result has .year, .month, .day attributes I can read.
Right. ISO 8601 is the date format — 2024-01-15, 2024-01-15T14:30:00, 2024-01-15T14:30:00+05:30. Always use it for storage and exchange.
What about other formats — 01/15/2024, Jan 15 2024?
Use datetime.strptime(string, format_string) — "string parse time." The format string uses %-codes:
datetime.strptime("01/15/2024", "%m/%d/%Y")
datetime.strptime("Jan 15 2024", "%b %d %Y")And strftime is the reverse — "string format time." Object → string.
When in doubt, use fromisoformat?
Always. If you control the format, store ISO. Reach for strptime only when the data comes from somewhere you don't control and they used a different shape.
datetime — the standard date/time modulefrom datetime import datetime, date, timedeltaThree main classes:
| Class | What it represents |
|---|---|
datetime | a moment — date + time |
date | just a calendar day |
timedelta | a duration (e.g., 2 days, 3 hours) |
We focus on datetime.
fromisoformatfrom datetime import datetime
datetime.fromisoformat("2024-01-15")
# datetime.datetime(2024, 1, 15, 0, 0)
datetime.fromisoformat("2024-01-15T14:30:00")
# datetime.datetime(2024, 1, 15, 14, 30)If the string isn't valid ISO, raises ValueError.
strptimedatetime.strptime("01/15/2024", "%m/%d/%Y")
datetime.strptime("Jan 15 2024", "%b %d %Y")
datetime.strptime("2024-01-15 14:30", "%Y-%m-%d %H:%M")Format codes you'll meet most:
| Code | Meaning | Example |
|---|---|---|
%Y | 4-digit year | 2024 |
%m | month (01–12) | 01 |
%d | day (01–31) | 15 |
%H | hour 24-clock | 14 |
%M | minute | 30 |
%S | second | 00 |
%b | abbreviated month name | Jan |
%B | full month name | January |
%a | abbreviated weekday | Mon |
%A | full weekday | Monday |
strftimed = datetime(2024, 1, 15)
d.strftime("%Y-%m-%d") # '2024-01-15'
d.strftime("%B %d, %Y") # 'January 15, 2024'
d.strftime("%Y-%m") # '2024-01' — useful for groupingd = datetime.fromisoformat("2024-01-15T14:30:00")
d.year # 2024
d.month # 1
d.day # 15
d.hour # 14
d.minute # 30
d.weekday() # 0=Monday, 6=Sundaya = datetime.fromisoformat("2024-01-01")
b = datetime.fromisoformat("2024-06-01")
a < b # True
b - a # datetime.timedelta(days=152)
(b - a).days # 152datetime.now() # current local datetime
date.today() # today's date (no time)fromisoformat is strict. "2024-1-15" (no zero-pad) doesn't parse — must be "2024-01-15". Use strptime if you have unpadded numbers.strptime and strftime have opposite directions. "p for parse, f for format." Easy to confuse.datetime without tzinfo is naive — it has no timezone. For a v1 script that doesn't cross zones, naive is fine. Cross-zone work needs pytz or zoneinfo (deferred).Create a free account to get started. Paid plans unlock all tracks.