🚀 Supercharge your YouTube channel's growth with AI.
Try YTGrowAI FreePython Datetime Module: Work with Dates and Times

Python code that calculates with calendar dates or clock times can keep those values as objects until it needs display text. The built-in datetime module provides the types and operations for that work.
In this piece, I’ll show you how to create date and time values, then handle local clock changes with a named time zone.
TL;DR
The Python datetime module is part of the standard library, so there is no separate package to install. Use date for calendar days, time for clock values, datetime for both, and timedelta for durations. Parse text with strptime(), format values with strftime(), and use zoneinfo.ZoneInfo for named time zones.
- Import only the classes your task needs.
- Keep dates and times as objects until you need to display or store text.
- Use aware datetimes when a time zone matters, especially for UTC or locations that observe daylight saving time.
What Is the Python datetime Module?
The datetime module provides constructors and operations for creating, parsing, comparing, and formatting calendar values. It also contains a class called datetime.
| Type | Represents | Typical use |
|---|---|---|
| date | Year, month, and day | Birthdays, due dates, reporting days |
| time | Hour, minute, second, and optional fractional seconds | A recurring opening time or alarm time |
| datetime | A date and a clock time, with optional time-zone information | An appointment or event timestamp |
| timedelta | A duration expressed in days, seconds, and microseconds | Adding an interval or finding a difference |
| timezone and ZoneInfo | Fixed offsets and named time-zone rules | Representing UTC or local civil time |
These objects are immutable. Operations such as adding an interval return a new value, leaving the original available for another calculation.
Installation and Import Syntax
Python ships the datetime module in its standard library, so everyday date and time tasks need no package installation.
Import the built-in module
If an import fails, check which Python interpreter runs your script before reaching for a package installer. Installing an unrelated package with the same name can make it harder to tell which code your program imports.
Choose the module form when you prefer explicit namespaces, or import selected class names when shorter references suit the file.
- With import datetime, refer to values as datetime.date, datetime.datetime, or datetime.time.
- With from datetime import date, datetime, timezone, call date.today() and datetime.now(timezone.utc) directly.
Because the module and class share a name, use the same import convention consistently within a file.
Datetime Constants and Common Properties
Use the module constants and type attributes to inspect supported years, bounds, and precision.
Constants describe limits and precision
Import MINYEAR and MAXYEAR to read the accepted year endpoints:
| Attribute | What it tells you | Example use |
|---|---|---|
| date.min / date.max | Earliest and latest calendar dates | Check that a stored date fits the supported range |
| time.min / time.max | Earliest and latest times of day | Validate a clock value |
| datetime.min / datetime.max | Earliest and latest combined date-time values | Use as type-level bounds for a comparison |
| date.resolution | One calendar day | Understand date precision |
| time.resolution / datetime.resolution | One microsecond | Understand clock and timestamp precision |
| timedelta.min / timedelta.max | Supported interval bounds | Validate an unusually large duration |
| timezone.utc | A fixed zero-offset UTC timezone | Mark a datetime as an aware UTC value |
Application rules can restrict a valid Python date to a narrower period, such as the open dates of a booking service.
Properties and constructors answer common questions
Many common operations are attributes or methods on the object you already have. Reading a component does not change the stored value. Use a constructor when you have separate numeric fields, and use a parsing method when the input arrives as text.
| Method or attribute | What it does | Check before using it |
|---|---|---|
| date.today(), .year, .month, .day | Gets the local date and its calendar components | Use an explicit zone for a date tied to a different region |
| datetime.now() | Gets the machine’s current local date and time | Pass a time zone such as timezone.utc when an aware UTC value is required |
| datetime.fromtimestamp(value, timezone.utc) | Converts Unix seconds to an aware UTC datetime | Specify the target zone rather than relying on the host’s local settings |
| datetime.combine(day, clock) | Joins an existing date and time | Useful when a form collects a date and clock time separately |
| date(), time(), timetz() | Extracts calendar or clock components from a datetime | timetz() retains time-zone information in the extracted clock value |
| .replace(year=…, month=…) | Returns a copy with selected fields changed | It validates the new date and can raise ValueError if that day does not exist |
| timedelta.total_seconds() and .seconds | Reads a duration as total seconds or the seconds remainder | .seconds excludes whole days, so it is not the full interval |
| datetime.timestamp() | Converts a datetime to seconds since the Unix epoch | A naive value uses machine-local rules. Prefer an aware value for consistent instants |
A time value stores clock fields but has no calendar date to advance. When an interval may cross midnight, combine the clock with a date and add a timedelta to the resulting datetime.
Compare two date objects to find a number of calendar days, and call strftime() when a report or user interface needs a particular text layout.
How to Work With Dates and Times Step by Step
Each example uses a named source file with its matching command, output, and terminal image. I ran the examples with Python 3.14.7 and captured the shown output. Python 3.9 or later is needed because the time-zone step uses the standard-library zoneinfo module.
Step 1: Get today’s date and build a datetime
Use date.today() to get the computer’s local calendar date. Access .month to get its month number. To construct a known appointment, pass year, month, and day to date, pass the clock fields to time, then combine them with datetime.combine().
from datetime import date, datetime, time
today = date.today()
appointment_date = date(2026, 10, 10)
appointment_time = time(9, 30)
appointment = datetime.combine(appointment_date, appointment_time)
print("Today:", today.isoformat())
print("Current month:", today.month)
print("Appointment:", appointment.isoformat(sep=" "))
print("Weekday index:", appointment.weekday())
Running python3 datetime_basics.py produced this output:
Today: 2026-10-10 Current month: 10 Appointment: 2026-10-10 09:30:00 Weekday index: 5

Saturday has index 5 here because weekday() numbers Monday as 0 and Sunday as 6.
Step 2: Parse and format date text
Pass strptime() the text and a format string that matches its layout. The directives used below are %Y for a four-digit year, %m for a month, %d for a day, %H for a 24-hour hour, and %M for minutes.
from datetime import datetime
source = "2026-10-10 09:30"
parsed = datetime.strptime(source, "%Y-%m-%d %H:%M")
print("Parsed:", parsed.isoformat())
print("Display:", parsed.strftime("%B %d, %Y at %I:%M %p"))
print("ISO date:", parsed.date().isoformat())
Running python3 datetime_parse_format.py produced:
Parsed: 2026-10-10T09:30:00 Display: October 10, 2026 at 09:30 AM ISO date: 2026-10-10

Here, strftime() turns the parsed value into display text. The isoformat() method returns a numeric representation, while date.fromisoformat(“2026-10-10”) parses an ISO date string.
Step 3: Add a duration or find a date difference
Pass day or clock components to timedelta for an interval. Subtracting two date objects returns a duration, and adding one to a date returns another date.
from datetime import date, datetime, timedelta
start = datetime(2026, 10, 10, 9, 30)
reminder = start + timedelta(days=7, hours=2)
print("Start:", start.isoformat(sep=" "))
print("Reminder:", reminder.isoformat(sep=" "))
print("Date difference:", (reminder.date() - start.date()).days, "days")
first_day_next_month = date(2026, 11, 1)
last_day = first_day_next_month - timedelta(days=1)
print("Last day of October:", last_day.isoformat())
Running python3 datetime_arithmetic.py produced:
Start: 2026-10-10 09:30:00 Reminder: 2026-10-17 11:30:00 Date difference: 7 days Last day of October: 2026-10-31

A timedelta stores a duration rather than a count of calendar months or years. To find a month’s last day, construct the first day of the following month and subtract one day, as shown. For rules such as adding a month while keeping the day where possible, use the standard-library calendar module to calculate valid dates.
Step 4: Use an IANA time zone for local clock rules
Use ZoneInfo(“America/Los_Angeles”), not a fixed UTC offset such as timezone(timedelta(hours=-5)), when the location’s daylight-saving rules matter.
from datetime import datetime, timedelta, timezone
from zoneinfo import ZoneInfo
utc_before = datetime(2026, 11, 1, 8, tzinfo=timezone.utc)
los_angeles = ZoneInfo("America/Los_Angeles")
local_before = utc_before.astimezone(los_angeles)
local_after = (utc_before + timedelta(hours=1)).astimezone(los_angeles)
print("Before clock change:", local_before.isoformat(sep=" "))
print("After one UTC hour:", local_after.isoformat(sep=" "))
print("UTC offset changed:", local_before.utcoffset() != local_after.utcoffset())
Running python3 datetime_timezone.py produced:
Before clock change: 2026-11-01 01:00:00-07:00 After one UTC hour: 2026-11-01 01:00:00-08:00 UTC offset changed: True

During a spring-forward change, some local clock readings do not exist. The fold flag distinguishes a repeated fall-back time. Decide separately whether to reject or adjust a missing local time.
The repeated clock reading in the output has two different offsets, so the offset identifies which occurrence it represents. For a stable instant, create an aware UTC value with datetime.now(timezone.utc) or convert an aware value with astimezone(timezone.utc), then convert it to a named local zone for display. Modern Python deprecates datetime.utcnow() because it returns a naive value.
Common strftime Format Codes
Choose a format code for each part of the output string. The same directives work with strptime() when parsing an input that uses that layout.
| Directive | Meaning | Example value |
|---|---|---|
| %Y | Four-digit year | 2026 |
| %m and %d | Numeric month and day | 10 and 05 |
| %H / %I | 24-hour / 12-hour clock | 17 / 05 |
| %M / %S | Minute / second | 30 / 09 |
| %p | AM or PM marker with a 12-hour value | PM |
| %a / %A | Abbreviated / full weekday name | Sat / Saturday |
| %b / %B | Abbreviated / full month name | Oct / October |
| %f | Microsecond field | 000000 |
| %z | Numeric UTC offset when present | +0000 |
- Pair %I with %p for a 12-hour clock.
- Use %H for a 24-hour clock.
- Use lowercase %m for the month. Uppercase %M means minute.
Names such as month and weekday text follow the active locale, so the same format may produce different words on machines with different locale settings. Numeric ISO output is usually a better choice for machine-readable storage. Use month names for people-facing output, and avoid depending on their exact spelling when parsing data from another system.
When the datetime includes an offset, %z adds that numeric UTC offset to the formatted output.
When to Use Python’s time Module
The separate time module provides timestamps, system clocks, and delays. Choose a function based on the kind of value your program needs.
| Function | What it returns or does | Use it for |
|---|---|---|
| time.time() | Seconds since the Unix epoch from the system wall clock | A calendar timestamp. System clock corrections can change the reading |
| time.monotonic() and time.perf_counter() | Monotonic counters with no calendar origin, and perf_counter() is designed for short performance measurements | Subtract readings to measure elapsed intervals or timeout deadlines |
| time.sleep(seconds) | Pauses the current thread for a requested interval | Delay work. Operating-system scheduling can make the pause longer |
Avoid confusing the time module with datetime.time
The class datetime.time stores hour, minute, and second fields.
If a program needs both names, alias the module with import time as time_module and import the clock-time class from datetime. The alias makes calls such as time_module.monotonic() unambiguous.
Python datetime Edge Cases to Check
Calendar validation catches impossible dates. Application rules must also determine which valid dates and offsets the program accepts.
| Situation | What happens | Safer choice |
|---|---|---|
| Format does not match input | strptime() raises ValueError | Match each directive and separator to the source string |
| Invalid date such as February 30 | Construction or parsing fails | Validate the value and handle the error where input enters the program |
| Naive and aware datetimes are compared | Ordering comparisons raise TypeError | Normalize both values to compatible aware datetimes, often UTC |
| Time zone is missing on a minimal system | ZoneInfo can raise ZoneInfoNotFoundError | Install or provide the IANA tzdata database for that environment |
| Month arithmetic uses a fixed number of days | The result can land in the wrong month | Use calendar-aware logic rather than treating a month as 30 days |
A naive value has no usable UTC offset. An aware value has a tzinfo with a defined utcoffset(). Comparing one of each with an ordering operator raises TypeError.
- For a timestamp received from an API, inspect whether its text contains Z or an offset such as +02:00, then parse and normalize it.
- For a wall-clock appointment in a location, attach its IANA zone and use the fold attribute to distinguish an ambiguous local time.
| Input or task | Useful method or check | Why it matters |
|---|---|---|
| Month and day without a year | Include the intended year before parsing | The default year may not be a leap year, so February 29 can fail |
| ISO year, week, and weekday | Use date.fromisocalendar(year, week, weekday) | The ISO week-year can differ from the calendar year near January 1 |
| Unix timestamp in milliseconds | Divide by 1,000 before datetime.fromtimestamp() | The conversion function expects seconds, so pass timezone.utc for an aware result |
| Ambiguous numeric date such as 03/04/2026 | Match the documented order or use ISO year-month-day | The text alone does not say whether the first number is month or day |
| Days in a particular month | Use calendar.monthrange(year, month)[1] | It returns the right month length, including in a leap year |
For a focused example of calendar fields, see AskPython’s guide to obtaining the current year and month. A separate week-number guide covers that related topic.
| Task | Behavior to account for | Safer handling |
|---|---|---|
| Schedule a monthly recurrence near month-end | A date such as the 31st may not exist in the following month | Choose whether to clamp to the final day or apply another calendar rule |
| Measure elapsed time across a daylight-saving change | Local wall-clock subtraction can differ from elapsed seconds | Convert both aware values to UTC before subtracting |
| Attach or convert a time zone | replace(tzinfo=zone) labels existing fields, while astimezone(zone) converts an aware value and preserves its instant | Choose based on whether the original value is naive or already aware |
Conclusion: Choose the Right Date and Time Type
Use date and time objects for calculations, then format the result where a screen, report, or API needs text.
The Python datetime reference documents the full API, and the zoneinfo reference explains named time-zone data. If your input is a pandas column rather than one Python value, use AskPython’s separate guide to converting data with pandas.to_datetime().
FAQ
These quick answers cover common questions that arise when starting with Python’s date and time types.


