Python 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.

TypeRepresentsTypical use
dateYear, month, and dayBirthdays, due dates, reporting days
timeHour, minute, second, and optional fractional secondsA recurring opening time or alarm time
datetimeA date and a clock time, with optional time-zone informationAn appointment or event timestamp
timedeltaA duration expressed in days, seconds, and microsecondsAdding an interval or finding a difference
timezone and ZoneInfoFixed offsets and named time-zone rulesRepresenting 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:

AttributeWhat it tells youExample use
date.min / date.maxEarliest and latest calendar datesCheck that a stored date fits the supported range
time.min / time.maxEarliest and latest times of dayValidate a clock value
datetime.min / datetime.maxEarliest and latest combined date-time valuesUse as type-level bounds for a comparison
date.resolutionOne calendar dayUnderstand date precision
time.resolution / datetime.resolutionOne microsecondUnderstand clock and timestamp precision
timedelta.min / timedelta.maxSupported interval boundsValidate an unusually large duration
timezone.utcA fixed zero-offset UTC timezoneMark 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 attributeWhat it doesCheck before using it
date.today(), .year, .month, .dayGets the local date and its calendar componentsUse an explicit zone for a date tied to a different region
datetime.now()Gets the machine’s current local date and timePass 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 datetimeSpecify the target zone rather than relying on the host’s local settings
datetime.combine(day, clock)Joins an existing date and timeUseful when a form collects a date and clock time separately
date(), time(), timetz()Extracts calendar or clock components from a datetimetimetz() retains time-zone information in the extracted clock value
.replace(year=…, month=…)Returns a copy with selected fields changedIt validates the new date and can raise ValueError if that day does not exist
timedelta.total_seconds() and .secondsReads 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 epochA 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
Python datetime date and month output in a terminal
The command and output from running datetime_basics.py.

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
Python datetime parsing and formatting output in a terminal
The parsing and formatting command output captured from datetime_parse_format.py.

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
Python datetime interval arithmetic and month-end output in a terminal
The interval and month-end calculation from datetime_arithmetic.py.

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
Python ZoneInfo conversion across a daylight saving time change in a terminal
The local clock repeats 1:00 as the UTC offset changes after the daylight saving transition.

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.

DirectiveMeaningExample value
%YFour-digit year2026
%m and %dNumeric month and day10 and 05
%H / %I24-hour / 12-hour clock17 / 05
%M / %SMinute / second30 / 09
%pAM or PM marker with a 12-hour valuePM
%a / %AAbbreviated / full weekday nameSat / Saturday
%b / %BAbbreviated / full month nameOct / October
%fMicrosecond field000000
%zNumeric 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.

FunctionWhat it returns or doesUse it for
time.time()Seconds since the Unix epoch from the system wall clockA 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 measurementsSubtract readings to measure elapsed intervals or timeout deadlines
time.sleep(seconds)Pauses the current thread for a requested intervalDelay 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.

SituationWhat happensSafer choice
Format does not match inputstrptime() raises ValueErrorMatch each directive and separator to the source string
Invalid date such as February 30Construction or parsing failsValidate the value and handle the error where input enters the program
Naive and aware datetimes are comparedOrdering comparisons raise TypeErrorNormalize both values to compatible aware datetimes, often UTC
Time zone is missing on a minimal systemZoneInfo can raise ZoneInfoNotFoundErrorInstall or provide the IANA tzdata database for that environment
Month arithmetic uses a fixed number of daysThe result can land in the wrong monthUse 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 taskUseful method or checkWhy it matters
Month and day without a yearInclude the intended year before parsingThe default year may not be a leap year, so February 29 can fail
ISO year, week, and weekdayUse date.fromisocalendar(year, week, weekday)The ISO week-year can differ from the calendar year near January 1
Unix timestamp in millisecondsDivide 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/2026Match the documented order or use ISO year-month-dayThe text alone does not say whether the first number is month or day
Days in a particular monthUse 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.

TaskBehavior to account forSafer handling
Schedule a monthly recurrence near month-endA date such as the 31st may not exist in the following monthChoose whether to clamp to the final day or apply another calendar rule
Measure elapsed time across a daylight-saving changeLocal wall-clock subtraction can differ from elapsed secondsConvert both aware values to UTC before subtracting
Attach or convert a time zonereplace(tzinfo=zone) labels existing fields, while astimezone(zone) converts an aware value and preserves its instantChoose 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.

Ninad
Ninad

A Python and PHP developer turned writer out of passion. Over the last 6+ years, he has written for brands including DigitalOcean, DreamHost, Hostinger, and many others. When not working, you'll find him tinkering with open-source projects, vibe coding, or on a mountain trail, completely disconnected from tech.

Articles: 136