Python datetime: Dates, Times, and Time Zones

Updated on: August 20, 2026
Reading time: 5 minutes
Manipulação de datas e calendário em Python

Dates and times appear in nearly every application: reports, reminders, subscriptions, logs, appointments, file names, and API payloads. They seem simple until time zones, daylight-saving changes, formatting, and calendar arithmetic enter the picture. Python’s standard datetime and zoneinfo modules provide the core tools needed to handle them clearly.

This Python datetime guide covers date, time, datetime, timedelta, parsing, formatting, time zones, comparisons, and practical patterns. It focuses on reliable application code rather than clever shortcuts.

The main datetime types

The module defines several related classes. date stores a calendar date, time stores a time of day, datetime combines both, and timedelta represents a duration. The official datetime documentation also distinguishes naive objects from timezone-aware objects.

from datetime import date, datetime, time, timedelta

today = date.today()
meeting_time = time(14, 30)
meeting = datetime(2026, 7, 10, 14, 30)
duration = timedelta(hours=1, minutes=15)

print(today)
print(meeting_time)
print(meeting + duration)

Get the current date and time

Use date.today() for a local calendar date. For an instant that may be exchanged between systems, prefer a timezone-aware datetime.

from datetime import datetime, timezone

now_utc = datetime.now(timezone.utc)
print(now_utc)

A naive datetime.now() has no timezone information. It may be acceptable for a local-only script, but it is risky for distributed systems because the value does not identify an unambiguous instant.

Create dates and datetimes

from datetime import date, datetime

release_date = date(2026, 9, 15)
deadline = datetime(2026, 9, 15, 17, 0)

print(release_date.year)
print(deadline.hour)

Constructors validate calendar rules. An impossible date, such as February 30, raises ValueError. Validate user input and provide a friendly message rather than storing malformed strings.

Format dates for people

Use strftime() to turn a date or datetime into a formatted string. Format codes represent components such as year, month, day, hour, and minute.

from datetime import datetime

moment = datetime(2026, 7, 10, 16, 45)

print(moment.strftime("%Y-%m-%d"))
print(moment.strftime("%B %d, %Y at %H:%M"))

Formatting is presentation. Keep dates as date or datetime objects during calculations and convert to text only at system boundaries or display time. The f-string formatting guide covers general output formatting.

Parse strings into datetime objects

Use strptime() when the input follows a known custom format. The format string must match the input exactly.

from datetime import datetime

text = "10/07/2026 16:45"
moment = datetime.strptime(text, "%d/%m/%Y %H:%M")

print(moment)

For ISO 8601-compatible strings, fromisoformat() is often clearer and faster to read.

from datetime import datetime

moment = datetime.fromisoformat("2026-07-10T16:45:00+00:00")
print(moment)

When parsing CSV or JSON, document the accepted format. The guides to CSV files and JSON in Python show where these conversions fit in a data pipeline.

Date arithmetic with timedelta

Add or subtract a timedelta for durations measured in days, seconds, microseconds, milliseconds, minutes, hours, or weeks.

from datetime import date, timedelta

today = date.today()
next_week = today + timedelta(weeks=1)
yesterday = today - timedelta(days=1)

print(next_week)
print(yesterday)

Subtracting two date or datetime objects returns a timedelta.

from datetime import date

start = date(2026, 7, 10)
end = date(2026, 8, 1)

difference = end - start
print(difference.days)

A timedelta is a fixed duration. “One month later” is not fixed because months have different lengths. Define the business rule explicitly or use a specialized calendar library when month arithmetic is required.

Compare dates and sort events

from datetime import datetime

events = [
    datetime(2026, 8, 1, 9, 0),
    datetime(2026, 7, 15, 14, 0),
    datetime(2026, 7, 20, 10, 30),
]

for event in sorted(events):
    print(event.isoformat())

Comparisons work naturally when objects are compatible. Do not compare a naive datetime with an aware datetime. Normalize values first. For custom record ordering, see Python sort versus sorted.

Work with time zones using zoneinfo

The standard zoneinfo module provides IANA time zone data. A named zone knows historical and daylight-saving transitions, unlike a permanently fixed numeric offset.

from datetime import datetime
from zoneinfo import ZoneInfo

sao_paulo = ZoneInfo("America/Sao_Paulo")
new_york = ZoneInfo("America/New_York")

local_meeting = datetime(2026, 7, 10, 10, 0, tzinfo=sao_paulo)
new_york_time = local_meeting.astimezone(new_york)

print(local_meeting)
print(new_york_time)

A common strategy is to store instants in UTC and convert to a user’s zone for display. Also preserve the intended named zone for recurring local events, because a fixed UTC time may not match the same wall-clock time after daylight-saving transitions.

Naive versus aware datetimes

A naive datetime has tzinfo=None. It can represent a local wall time, but the object alone does not say which location or offset applies. An aware datetime includes timezone information and represents an identifiable point on the global timeline.

from datetime import datetime, timezone

naive = datetime(2026, 7, 10, 12, 0)
aware = datetime(2026, 7, 10, 12, 0, tzinfo=timezone.utc)

print(naive.tzinfo)
print(aware.tzinfo)

Do not attach a timezone to an arbitrary naive value unless you know what zone the original wall time meant. Converting an existing instant and labeling an unzoned wall time are different operations.

Build a deadline helper

from datetime import datetime, timezone

def seconds_until(deadline: datetime) -> float:
    if deadline.tzinfo is None:
        raise ValueError("deadline must be timezone-aware")

    now = datetime.now(timezone.utc)
    normalized = deadline.astimezone(timezone.utc)
    return max(0.0, (normalized - now).total_seconds())

The function rejects ambiguous input, normalizes both values to UTC, and never returns a negative wait. Type hints make the contract visible; see Python type hints for more examples.

Use dates in file names and logs

from datetime import datetime, timezone
from pathlib import Path

timestamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
path = Path("exports") / f"report-{timestamp}.txt"

path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("Report created.", encoding="utf-8")

print(path)

A sortable year-month-day order keeps generated files chronological. For application events, the logging module provides configurable timestamps and structured output.

Common mistakes

  • Storing dates as inconsistent human-formatted strings.
  • Using naive datetimes for events exchanged between systems.
  • Assuming every day has exactly 24 local hours across daylight-saving transitions.
  • Treating a month as a fixed number of days.
  • Parsing user input without handling ValueError.
  • Comparing naive and timezone-aware values.
  • Using local server time as a universal reference.

Frequently asked questions

Should I store UTC in a database?

UTC is a strong default for instants such as creation times and completed transactions. For future appointments and recurring events, also store the relevant named time zone and business rules so the intended local time can be reconstructed.

What is the best date string format?

ISO 8601 is readable, sortable in many common forms, and widely supported. Include an offset or Z for instants. A bare date such as 2026-07-10 is appropriate when no time of day exists.

How do I calculate age?

Age is calendar-based, not simply elapsed days divided by 365. Compare month and day relative to the current year and define rules for leap-day birthdays.

Final thoughts

Reliable datetime code begins by deciding what a value represents: a calendar date, local wall time, duration, or global instant. Keep structured objects during calculations, use aware datetimes for exchanged instants, convert to a named zone for display, and treat calendar arithmetic as a business rule rather than a fixed-duration shortcut.

Share:

Facebook
WhatsApp
Twitter
LinkedIn

Article content

    Related articles

    Document and inbox representing local email stores with Python mailbox
    Libraries and Modules
    Foto de perfil de Leandro Hirt da Academify

    Python mailbox: Local Email Stores

    Learn Python mailbox to read, create, and migrate Maildir, mbox, and MH stores with locking, flags, message parsing, and safe

    Ler mais

    Tempo de leitura: 5 minutos
    12/08/2026
    Text editor representing formatting with Python textwrap
    Libraries and Modules
    Foto de perfil de Leandro Hirt da Academify

    Python textwrap: Format Text

    Learn Python textwrap to wrap, fill, shorten, indent, and dedent text with controlled width, whitespace, long words, and reusable settings.

    Ler mais

    Tempo de leitura: 4 minutos
    10/08/2026
    Folder and magnifying glass representing file-name filters with Python fnmatch
    Libraries and Modules
    Foto de perfil de Leandro Hirt da Academify

    Python fnmatch: Filter File Names

    Learn Python fnmatch to filter file names with shell wildcards, control case sensitivity, exclude patterns, and distinguish glob from regex.

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Monitor with binary data representing compact numeric arrays in Python
    Libraries and Modules
    Foto de perfil de Leandro Hirt da Academify

    Python array: Compact Numeric Data

    Learn Python array for compact numeric storage, binary files, byte order, memory views, and safe buffer interoperability.

    Ler mais

    Tempo de leitura: 6 minutos
    10/08/2026
    Color wheel representing RGB, HSV, and HLS conversions with Python colorsys
    Libraries and Modules
    Foto de perfil de Leandro Hirt da Academify

    Python colorsys: RGB, HSV, and HLS

    Learn Python colorsys to convert colors between RGB, HSV, HLS, and YIQ, generate palettes, and avoid scale and precision mistakes.

    Ler mais

    Tempo de leitura: 5 minutos
    09/08/2026
    Configuration icon representing plist files with Python plistlib
    Libraries and Modules
    Foto de perfil de Leandro Hirt da Academify

    plistlib: Read and Write Apple Plist Files

    Learn Python plistlib to read and write XML and binary plist files, validate data, handle dates, bytes, and UIDs safely.

    Ler mais

    Tempo de leitura: 6 minutos
    08/08/2026