The essentials

Quick reference

One focused task per row. Jump to the related section for complete, working examples.

UseSyntaxExamples
Create a calendar dateday = date(2026, 8, 12)View examples
Move by elapsed daystomorrow = day + timedelta(days=1)View examples
Combine date and timemeeting = datetime.combine(day, time(9, 30))View examples
Read the current UTC instantnow = datetime.now(UTC)View examples
Construct an aware datetimeinstant = datetime(2026, 8, 12, 15, tzinfo=UTC)View examples
Convert the same instantlocal = instant.astimezone(target_zone)View examples
Parse ISO-formatted textvalue = datetime.fromisoformat('2026-08-12T15:30:00+00:00')View examples
Emit ISO-formatted texttext = value.isoformat(timespec='seconds')View examples
Parse a declared formatvalue = datetime.strptime(text, '%Y-%m-%d %H:%M')View examples
Format for displaylabel = value.strftime('%Y-%m-%d %H:%M')View examples
Load an IANA time zonezone = ZoneInfo('America/Sao_Paulo')View examples
Decode a POSIX timestampinstant = datetime.fromtimestamp(timestamp, tz=UTC)View examples
Advance a local schedulenext_run = local_run + timedelta(days=1)View examples
Measure elapsed timeelapsed = end.astimezone(UTC) - start.astimezone(UTC)View examples
Read a duration in secondsseconds = duration.total_seconds()View examples
Disambiguate a repeated wall timelater = local.replace(fold=1)View examples

Date and time code becomes reliable when it distinguishes calendar values, wall-clock readings, durations, and unique instants. Use aware datetimes for instants, UTC at storage and protocol boundaries, and named IANA zones when civil rules matter. Parse declared formats, preserve the original zone when it carries business meaning, and test transitions explicitly instead of relying on the machine's clock or local-zone configuration.

Step by step

Detailed examples

01

Choose the smallest temporal type that expresses the domain

date represents a calendar day, time represents wall-clock fields, datetime combines both, and timedelta represents a duration. These objects are immutable. A naive datetime has no usable UTC offset and cannot by itself identify a global instant; that can be correct for concepts such as an all-day birthday or a not-yet-zoned appointment. datetime assumes every civil day has exactly 86,400 seconds and does not model leap seconds.

Build a leap-day appointment from calendar parts
from datetime import date, datetime, time, timedelta

leap_day = date(2024, 2, 28) + timedelta(days=1)
meeting = datetime.combine(leap_day, time(9, 30))

print(leap_day.isoformat())
print(meeting)
print(meeting.weekday())
Output
2024-02-29
2024-02-29 09:30:00
3
Back to quick reference ↑
02

Represent instants with aware datetimes

An aware datetime has a tzinfo object that supplies a UTC offset. Prefer datetime.now(UTC) over utcnow(), which has been deprecated since Python 3.12 because it returns a naive value that many methods interpret as local time. The UTC singleton was added in Python 3.11; timezone.utc is the compatible spelling on older Python versions. astimezone converts the same instant, while replace(tzinfo=new_zone) merely attaches new zone metadata and normally must not be used as a conversion.

Convert one instant to a fixed-offset zone
from datetime import UTC, datetime, timedelta, timezone

instant = datetime(2025, 1, 15, 15, 0, tzinfo=UTC)
brt = timezone(timedelta(hours=-3), 'BRT')
local = instant.astimezone(brt)

print(instant.isoformat())
print(local.isoformat())
print(local.tzname())
print(local.astimezone(UTC) == instant)
Output
2025-01-15T15:00:00+00:00
2025-01-15T12:00:00-03:00
BRT
True
Back to quick reference ↑
03

Parse machine formats and presentation formats separately

fromisoformat and isoformat are the direct choices for supported ISO 8601 forms and preserve an included numeric offset. strptime handles a declared input format and rejects mismatches; strftime creates display text. A parsed numeric offset is fixed-offset metadata, not a historical IANA zone identity. Avoid ambiguous inputs, locale-dependent directives, and unbounded acceptance of many guessed formats. The complete strftime directive set varies because Python delegates some behavior to the platform C library.

Parse an offset and render controlled representations
from datetime import datetime

instant = datetime.fromisoformat('2025-08-12T14:05:09+00:00')
appointment = datetime.strptime('12 Aug 2025 14:05', '%d %b %Y %H:%M')

print(instant.isoformat(timespec='seconds'))
print(instant.strftime('%Y-%m-%d %H:%M %z'))
print(appointment.strftime('%Y-%m-%dT%H:%M'))
Output
2025-08-12T14:05:09+00:00
2025-08-12 14:05 +0000
2025-08-12T14:05
Back to quick reference ↑
04

Use IANA zones for political civil-time rules

ZoneInfo, added in Python 3.9, applies the IANA database's historical and current offset rules. It reads system zone data and falls back to the first-party tzdata package; declare tzdata as a dependency when deployment platforms may lack a database. A ZoneInfo key such as America/Sao_Paulo is program data, not a user-friendly label. Rule changes can alter results for future dates, so pin and update time-zone data deliberately where reproducibility matters.

Render one UTC instant in two named zones
from datetime import UTC, datetime
from zoneinfo import ZoneInfo

instant = datetime(2024, 7, 1, 16, 0, tzinfo=UTC)
sao_paulo = instant.astimezone(ZoneInfo('America/Sao_Paulo'))
tokyo = instant.astimezone(ZoneInfo('Asia/Tokyo'))

print(instant.isoformat())
print(sao_paulo.isoformat())
print(tokyo.isoformat())
Output
2024-07-01T16:00:00+00:00
2024-07-01T13:00:00-03:00
2024-07-02T01:00:00+09:00
Back to quick reference ↑
05

Separate recurring wall time from elapsed duration

Adding one day to an aware local datetime advances its calendar fields and retains its zone, which is often right for a daily local schedule. Across an offset transition, the resulting instants can be 23 or 25 hours apart. When measuring elapsed time, convert endpoints to UTC before subtraction. Subtraction between aware datetimes that share the same tzinfo object ignores changing offsets and follows wall-clock arithmetic, so write tests around every transition relevant to the application.

Compare a daily schedule with elapsed time
from datetime import UTC, datetime, timedelta
from zoneinfo import ZoneInfo

new_york = ZoneInfo('America/New_York')
start = datetime(2024, 3, 9, 12, 0, tzinfo=new_york)
next_run = start + timedelta(days=1)
elapsed = next_run.astimezone(UTC) - start.astimezone(UTC)

print(start.isoformat())
print(next_run.isoformat())
print(elapsed)
print(elapsed.total_seconds() / 3600)
Output
2024-03-09T12:00:00-05:00
2024-03-10T12:00:00-04:00
23:00:00
23.0
Back to quick reference ↑
06

Resolve repeated and missing wall-clock readings at input boundaries

When clocks move backward, two instants can share one local reading. PEP 495's fold attribute chooses the earlier offset with fold=0 and the later offset with fold=1. When clocks move forward, some local readings do not exist; attaching ZoneInfo does not validate or reject such a reading. Define a product policy for ambiguous and missing input, preserve an offset or fold when necessary, and prefer conversion from a known instant when ingesting timestamps.

Select each occurrence of a repeated local time
from datetime import UTC, datetime
from zoneinfo import ZoneInfo

los_angeles = ZoneInfo('America/Los_Angeles')
earlier = datetime(2020, 11, 1, 1, 30, tzinfo=los_angeles, fold=0)
later = earlier.replace(fold=1)

print(earlier.isoformat())
print(later.isoformat())
print(later.astimezone(UTC) - earlier.astimezone(UTC))
Output
2020-11-01T01:30:00-07:00
2020-11-01T01:30:00-08:00
1:00:00
Back to quick reference ↑

Local code tester

Explore aware date-time conversion

Convert a fixed UTC instant to an explicit fixed offset without consulting the current clock or machine-local zone.

Runs in your browser
Output
Press Run to load Python locally.

Sources and further reading

References

Authoritative documentation used to verify and expand this cheat sheet.

  1. Python Software Foundationdatetime — Basic date and time typesdocs.python.org
  2. Python Software Foundationzoneinfo — IANA time zone supportdocs.python.org
  3. Python Software FoundationPEP 495 — Local Time Disambiguationpeps.python.org
  4. Python Software FoundationPEP 615 — Support for the IANA Time Zone Database in the Standard Librarypeps.python.org

Help us improve

Found a typo or missing example?

Tell us what would make this cheat sheet clearer, more complete, or more useful.

Share feedback