datetime

Five value types do the work: date, time, datetime, timedelta and timezone. The traps are naive vs aware datetimes, the formatting directives, and timedelta.seconds not meaning what it says.

Dates & timesPython 2.3+Live demo
Import
import datetime
from datetime import date, time, datetime, timedelta, timezone, UTC
Public API
date, time, datetime, timedelta, timezone, tzinfo, MINYEAR, MAXYEAR, UTC
Calendar
Proleptic Gregorian, years 1..9999, microsecond resolution, no leap seconds
Speed
C accelerator _datetime (Modules/_datetimemodule.c); pure-Python fallback Lib/_pydatetime.py
Time zones
Fixed offsets built in (timezone); named zones with DST rules are in the zoneinfo module (3.9+)

Demo

Live evaluation
Parse an ISO timestamp, add a timedelta, format the result back as ISO 8601.
Try:
Inputs
startstran ISO 8601 timestamp
daysintdays to add
hoursinthours to add
Code
from datetime import datetime, timedelta
start = datetime.fromisoformat('2026-09-29T14:30')
(start + timedelta(days=30, hours=12)).isoformat()
Result
'2026-10-30T02:30:00'

All three tabs start from fromisoformat, the reliable way to get a datetime from text. Adding a timedelta keeps the UTC offset you started with (+01:00 stays +01:00 — a fixed offset never changes for daylight saving), a negative difference prints as "-271 days, 0:00:00" rather than "-271 days", and %z only has something to print when the datetime carries an offset.

Members

Methods & attributes18
LIVE
datetime.astimezone
astimezone(tz=None)
Convert an aware datetime to another time zone: same instant, different wall-clock reading. Without tz it converts to the machine's local zone.
LIVE
datetime.combine / date() / time() / timetz()
combine(date, time, tzinfo=time.tzinfo)
Join a date and a time into a datetime (combine), or split a datetime into its date, its time, or its time with tzinfo.
LIVE
datetime.ctime
ctime()
The fixed C-style text form "Tue Sep 29 14:30:05 2026" — English names, space-padded day, no zone.
LIVE
date.year / month / day
d.year · d.month · d.day
The three read-only integer fields of a date — and of a datetime, which inherits them.
LIVE
datetime.fromisoformat / isoformat
fromisoformat(date_string)
Parse ISO 8601 text into a date, time or datetime (fromisoformat), and write one out as ISO 8601 (isoformat) — the exact, lossless round trip.
LIVE
datetime.fromtimestamp / utcfromtimestamp
fromtimestamp(timestamp, tz=None)
Convert a POSIX timestamp (seconds since 1970-01-01 UTC) into a datetime or date. Pass tz for an aware result; utcfromtimestamp is deprecated.
LIVE
date.isocalendar / fromisocalendar
isocalendar()
ISO 8601 week dates: isocalendar() gives (year, week, weekday); fromisocalendar(year, week, day) builds the date back.
LIVE
date.min / max / resolution (and friends)
date.min · date.max · date.resolution
The smallest value, the largest value and the smallest step of each datetime type: date, datetime, time, timedelta — plus timezone.min and timezone.max.
LIVE
datetime.replace
replace(year=…, month=…, day=…, hour=…, minute=…, second=…, microsecond=…, tzinfo=…, *, fold=…)
Return a copy with some fields changed — the way to "set" the day, truncate to the minute, or attach and remove a tzinfo.
LIVE
datetime.strftime / strptime
strftime(format)
Format a date, time or datetime as text with %-directives (strftime), and parse text back into a datetime with the same directives (strptime).
LIVE
datetime.hour / minute / second / microsecond / tzinfo / fold
dt.hour · dt.minute · dt.second · dt.microsecond · dt.tzinfo · dt.fold
The read-only time-of-day fields shared by datetime and time: hour, minute, second, microsecond, the tzinfo object and the fold flag.
LIVE
timedelta.total_seconds / days / seconds / microseconds
total_seconds()
Read a duration back out: the three stored fields days, seconds and microseconds, or the whole length as a float number of seconds.
LIVE
datetime.timestamp
timestamp()
Seconds since 1970-01-01T00:00:00Z as a float — the POSIX timestamp of an aware datetime (naive values are taken as local time).
LIVE
datetime.timetuple / utctimetuple
timetuple()
Convert to a time.struct_time for the time module: timetuple() keeps the local fields, utctimetuple() converts an aware value to UTC first.
LIVE
date.today / datetime.now / utcnow
now(tz=None)
The current date or date and time: date.today(), datetime.now(tz), and the deprecated naive datetime.utcnow().
LIVE
date.toordinal / fromordinal
toordinal()
Convert a date to its proleptic Gregorian day number (0001-01-01 is day 1) and back.
LIVE
datetime.utcoffset / tzname / dst
utcoffset() · dt.tzname() · dt.dst()
Ask an aware value for its UTC offset, its zone name and its daylight-saving component; naive values answer None.
LIVE
date.weekday / isoweekday
weekday()
The day of the week as a number: weekday() gives Monday = 0 … Sunday = 6, isoweekday() gives Monday = 1 … Sunday = 7.

Common patterns

The current time, correctly
Ask for an aware datetime in UTC; convert to local time only for display.
from datetime import datetime, UTC
now = datetime.now(UTC)
stamp = now.isoformat()  # 2026-09-29T12:00:00.123456+00:00
Parse, shift, format
fromisoformat → arithmetic with timedelta → strftime or isoformat.
from datetime import datetime, timedelta
due = datetime.fromisoformat('2026-09-29T09:00') + timedelta(days=14)
print(due.strftime('%d %b %Y'))
Age of something in days
date - date is a timedelta; .days is the whole-day count.
from datetime import date
age_days = (date.today() - created_on).days
Convert between offsets
astimezone keeps the instant and changes the wall-clock reading.
from datetime import datetime, timedelta, timezone
ist = timezone(timedelta(hours=5, minutes=30))
local = utc_dt.astimezone(ist)

Examples

1. A datetime and its parts
from datetime import datetime dt = datetime(2026, 9, 29, 14, 30) (dt.year, dt.month, dt.day, dt.hour, dt.minute)
Returns
(2026, 9, 29, 14, 30)
2. repr vs str
from datetime import datetime dt = datetime(2026, 9, 29, 14, 30) print(dt) dt
Returns
2026-09-29 14:30:00 datetime.datetime(2026, 9, 29, 14, 30)
3. Add a duration
from datetime import date, timedelta date(2026, 9, 29) + timedelta(weeks=2)
Returns
datetime.date(2026, 10, 13)
4. Difference of two datetimes
from datetime import datetime datetime(2026, 9, 29, 18, 0) - datetime(2026, 9, 28, 9, 15)
Returns
datetime.timedelta(days=1, seconds=31500)
5. Parse ISO 8601 text
from datetime import datetime datetime.fromisoformat('2026-09-29T14:30:00Z')
Returns
datetime.datetime(2026, 9, 29, 14, 30, tzinfo=datetime.timezone.utc)
6. Format with strftime
from datetime import date date(2026, 9, 29).strftime('%d %B %Y')
Returns
'29 September 2026'
7. Parse with strptime
from datetime import datetime datetime.strptime('29/09/2026 14:30', '%d/%m/%Y %H:%M')
Returns
datetime.datetime(2026, 9, 29, 14, 30)
8. Dates are validated
from datetime import date date(2026, 2, 29)
Returns
ValueError: day is out of range for month

Pitfalls

1. import datetime vs from datetime import datetime
The module and its main class share a name. After import datetime, the class is datetime.datetime.
module, not class
import datetime
datetime.fromisoformat("2026-09-29")
AttributeError: module 'datetime' has no attribute 'fromisoformat'
the class
import datetime
datetime.datetime.fromisoformat("2026-09-29")
datetime.datetime(2026, 9, 29, 0, 0)
2. Mixing naive and aware datetimes
A naive datetime has no offset, so Python refuses to order or subtract it against an aware one. Make both aware.
naive < aware
from datetime import datetime, UTC
datetime(2026, 9, 29) < datetime.now(UTC)
TypeError: can't compare offset-naive and offset-aware datetimes
both aware
from datetime import datetime, UTC
datetime(2026, 9, 29, tzinfo=UTC) < datetime(2026, 9, 30, tzinfo=UTC)
True
3. timedelta.seconds is not the total
A timedelta stores days, seconds (0..86399) and microseconds separately. .seconds drops the days.
.seconds
from datetime import timedelta
timedelta(days=2, hours=1).seconds
3600
.total_seconds()
from datetime import timedelta
timedelta(days=2, hours=1).total_seconds()
176400.0

When to use

Use it
  • Calendar dates, timestamps and durations in application code
  • Parsing and producing ISO 8601 text (APIs, logs, JSON)
  • Date arithmetic: deadlines, ages, "N days from now", differences
Reach for something else
  • Named time zones with daylight saving rules → zoneinfo (3.9+)
  • Monotonic timing of code → time.perf_counter()
  • Calendars and month-length tables → the calendar module
  • Adding months or years → there is no timedelta(months=…); use replace() or a third-party library

Notes

CPython impl
Modules/_datetimemodule.c, imported by Lib/datetime.py; Lib/_pydatetime.py is the pure-Python fallback (strptime is shared: Lib/_strptime.py)
Naive/aware
A datetime or time with tzinfo=None is naive; with a tzinfo whose utcoffset() is not None it is aware
Immutability
Every object is immutable and hashable — replace(), astimezone() and arithmetic return new objects
Range
date.min is 0001-01-01 and date.max is 9999-12-31; going past either raises OverflowError: date value out of range

FAQ

import datetime binds the module, so the class is datetime.datetime and the date class is datetime.date. from datetime import datetime binds the class itself under the same name — after that, datetime.date is the method that extracts the date part, not the date class. Pick one style per file.