Working With Dates and Times in Python
SkillVeris Team
Engineering Team

Python's built-in datetime module is the standard way to represent, parse, format, and calculate with dates and times.
In this guide, you'll learn:
- A datetime object combines a date and a time; date and time objects handle each part separately.
- strftime formats a datetime into a string, and strptime parses a string back into a datetime.
- timedelta represents a span of time, letting you add or subtract days, hours, and seconds cleanly.
- Always store and compute in UTC and convert to local time only for display to avoid timezone bugs.
1How Python Handles Dates and Times
Python manages dates and times through the built-in datetime module, which provides objects for dates, times, and combined datetimes plus the timedelta type for durations. Import it and you can capture the current moment, build a specific date, or measure the gap between two events without any external package.
The module distinguishes several object types. A date holds year, month, and day. A time holds hour, minute, second, and microsecond. A datetime combines both, and a timedelta represents a length of time rather than a point on the calendar. Knowing which one you need is half the battle.
2Creating Date and Time Objects
You can grab the current moment or construct an exact one. datetime.now() returns the current local datetime, while datetime(2026, 7, 19, 14, 30) builds a specific one. For dates alone, use the date class.
- from datetime import datetime, date, time, timedelta
- now = datetime.now() # current local date and time
- today = date.today() # just the date
- birthday = date(1991, 8, 25) # a specific date
- meeting = datetime(2026, 7, 19, 14, 30) # specific datetime
- noon = time(12, 0) # a time of day
3Formatting and Parsing
Converting between datetimes and strings is a daily task. strftime turns a datetime into a formatted string using directive codes, and strptime does the reverse by parsing a string according to a format you specify. The two are mirror images and share the same directive codes.
💡Pro Tip
For machine-readable output, use dt.isoformat() and datetime.fromisoformat(). ISO 8601 strings sort correctly as text and parse unambiguously across systems.
Common Directives
Format codes are single letters preceded by a percent sign. A few cover most needs, and you combine them freely with literal text.
dt.strftime('%Y-%m-%d') # 2026-07-19
dt.strftime('%H:%M:%S') # 14:30:00
dt.strftime('%A, %B %d') # Sunday, July 19
datetime.strptime('2026-07-19', '%Y-%m-%d') # parse back
# %Y year, %m month, %d day, %H hour, %M minute, %S second4Date Arithmetic With timedelta
To add or subtract time, use timedelta. Subtracting two datetimes yields a timedelta describing the gap between them, and adding a timedelta to a datetime shifts it forward or backward. This handles month lengths and leap years for you, so you never hand-count days.
- tomorrow = now + timedelta(days=1)
- last_week = now - timedelta(weeks=1)
- deadline = now + timedelta(hours=36)
- gap = date(2026, 12, 25) - date.today() # a timedelta
- gap.days # number of whole days between them
5Dealing With Time Zones
Time zones are where date handling gets tricky. A naive datetime carries no timezone information; an aware one does. Mixing them causes errors and subtle bugs. The standard zoneinfo module, added in Python 3.9, provides real timezone data so you can attach and convert zones correctly.
- from zoneinfo import ZoneInfo
- from datetime import datetime, timezone
- utc_now = datetime.now(timezone.utc) # aware, in UTC
- ny = utc_now.astimezone(ZoneInfo('America/New_York'))
- # naive datetimes have no tzinfo and cannot be safely compared
⚠️Watch Out
Never compare or subtract a naive datetime and an aware one; Python raises a TypeError. Decide early whether your datetimes carry timezone info and stay consistent.
6Extracting Parts and Comparing Dates
Once you have a datetime, you can read its individual parts through attributes and compare two datetimes directly with the usual operators. Attributes like year, month, day, hour, and weekday() let you pull out exactly the piece you need, while comparisons tell you which moment came first.
- now.year # 2026
- now.month # 7
- now.weekday() # Monday is 0, Sunday is 6
- meeting < now # True if meeting is earlier
- max(date_a, date_b) # the later of two dates
7Best Practices
A short list of habits eliminates most date and time bugs before they happen.
- Store and compute in UTC; convert to local time only when displaying to a user.
- Use aware datetimes throughout so comparisons never surprise you.
- Prefer ISO 8601 (isoformat) for storage and data interchange.
- Reach for zoneinfo for time zones instead of hardcoding offsets that ignore daylight saving.
- Use dateutil.parser for messy, human-entered date strings you cannot fully control.
8Key Takeaways
The datetime module covers nearly every date need once you know its pieces.
- datetime, date, time, and timedelta each model a different concept.
- strftime formats and strptime parses, using shared directive codes.
- timedelta powers safe date arithmetic across months and leap years.
- Use UTC internally and zoneinfo for correct timezone conversions.
- Keep datetimes consistently aware to avoid comparison errors.
9Frequently Asked Questions
Q: What is the difference between date, time, and datetime in Python? A: A date holds only a calendar day (year, month, day), a time holds only a clock time (hour, minute, second), and a datetime combines both into a single object representing an exact moment.
Q: How do I convert a string to a datetime? A: Use datetime.strptime with a format string that matches the input, for example datetime.strptime('2026-07-19', '%Y-%m-%d'). For ISO 8601 strings, datetime.fromisoformat is simpler.
Q: Why do I get a TypeError comparing two datetimes? A: You are likely comparing a naive datetime (no timezone) with an aware one (has timezone). Make both aware, typically by working in UTC, so they can be compared safely.
Q: Should I store dates in UTC or local time? A: Store in UTC. Compute and persist everything in UTC and convert to the user's local time zone only at display time. This avoids daylight-saving and offset bugs entirely.
Related Reading
Get The Print Version
Download a PDF of this article for offline reading.
About the Publisher
SkillVeris Team
Engineering Team
Our engineering writers turn abstract code concepts into hands-on, project-driven learning experiences.
View all postsRelated Posts
Never miss an update
Get the latest tutorials and guides delivered to your inbox.
No spam. Unsubscribe anytime.