datetime.utcoffset / tzname / dst

The same three questions exist on datetime, time, timezone and tzinfo. On a datetime or time they simply forward to tzinfo — passing the datetime itself (or None for a time) — and return None when there is no tzinfo.

datetime / time / tzinfo methodPython 2.3+Live demo
Common call
dt.utcoffset()
Returns
datetime.timedelta(seconds=7200) for +02:00; None if naive
Replaces
Parsing "+02:00" out of strings
Watch out
timezone.dst() is always None — fixed offsets know nothing of DST
dt.utcoffset() · dt.tzname() · dt.dst()
→ timedelta | str | None

Demo

Live evaluation
All three questions on one parsed timestamp.
Try:
Inputs
whenstran ISO 8601 timestamp
Code
from datetime import datetime
dt = datetime.fromisoformat('2026-09-29T14:30+02:00')
(dt.utcoffset(), dt.tzname(), dt.dst())
Result
(datetime.timedelta(seconds=7200), 'UTC+02:00', None)

Negative offsets are normalized timedeltas (-05:30 is days=-1, seconds=66600) but total_seconds() gives the plain signed value. Naive values return None for all three — and None.total_seconds() is an AttributeError, so check for None first.

Parameters

NameTypeRequiredDescription
dtdatetime | NoneyesOnly on timezone / tzinfo methods: the datetime being asked about. timezone accepts None or a datetime and ignores it.

Return value

timedelta | str | None — utcoffset and dst: a timedelta or None. tzname: a str or None.

Attributes

AttributeTypeMeaning
utcoffset()timedelta | NoneLocal time minus UTC, DST included: +02:00 → timedelta(seconds=7200), -05:00 → timedelta(days=-1, seconds=68400).
tzname()str | Nonetimezone: its name, or "UTC±HH:MM" generated from the offset ("UTC" for zero). zoneinfo: abbreviations like "CEST".
dst()timedelta | NoneHow much of the offset is daylight saving. None for timezone objects and naive values.

Common patterns

Offset as "+HH:MM" text
strftime %:z (3.12+) or isoformat already contain it.
label = dt.strftime('%:z')  # '+02:00'
Offset in minutes, None-safe
Guard naive values.
off = dt.utcoffset()
minutes = None if off is None else off // timedelta(minutes=1)
Is daylight saving in effect?
Only meaningful with a DST-aware tzinfo such as zoneinfo.
in_dst = bool(dt.dst())

Examples

1. An aware datetime
from datetime import datetime, timedelta, timezone dt = datetime(2026, 9, 29, 14, 30, tzinfo=timezone(timedelta(hours=2))) (dt.utcoffset(), dt.tzname(), dt.dst())
Returns
(datetime.timedelta(seconds=7200), 'UTC+02:00', None)
2. A naive datetime
from datetime import datetime dt = datetime(2026, 9, 29) (dt.utcoffset(), dt.tzname(), dt.dst())
Returns
(None, None, None)
3. On a time
from datetime import time, timedelta, timezone t = time(14, tzinfo=timezone(timedelta(hours=-3), 'BRT')) (t.utcoffset(), t.tzname())
Returns
(datetime.timedelta(days=-1, seconds=75600), 'BRT')
4. On the timezone itself
from datetime import UTC (UTC.utcoffset(None), UTC.tzname(None), UTC.dst(None))
Returns
(datetime.timedelta(0), 'UTC', None)
5. The dt argument is required
from datetime import timedelta, timezone timezone(timedelta(hours=1)).utcoffset()
Returns
TypeError: timezone.utcoffset() takes exactly one argument (0 given)
6. The abstract base
from datetime import tzinfo tzinfo().tzname(None)
Returns
NotImplementedError: a tzinfo subclass must implement tzname()

Pitfalls

1. Calling total_seconds() on a naive offset
Naive datetimes return None, which has no methods.
naive
from datetime import datetime
datetime(2026, 9, 29).utcoffset().total_seconds()
AttributeError: 'NoneType' object has no attribute 'total_seconds'
check first
from datetime import datetime
off = datetime(2026, 9, 29).utcoffset()
0.0 if off is None else off.total_seconds()
0.0
2. Passing an int to timezone.utcoffset
The argument is the datetime being asked about (or None), not an hour.
utcoffset(5)
from datetime import timedelta, timezone
timezone(timedelta(hours=1)).utcoffset(5)
TypeError: utcoffset(dt) argument must be a datetime instance or None, not int
utcoffset(None)
from datetime import timedelta, timezone
timezone(timedelta(hours=1)).utcoffset(None)
datetime.timedelta(seconds=3600)

When to use

Use it
  • Finding out whether and how a value is zoned
  • Displaying or storing the offset separately
Reach for something else
  • Converting between zones → astimezone
  • Deciding DST with a fixed offset — timezone.dst() is always None

Notes

CPython impl
datetime/time methods call tzinfo.utcoffset(self) (a time passes None) and validate the result: None or a timedelta strictly within ±24 h
Naive
No tzinfo → all three return None
timezone
utcoffset → the fixed offset, dst → None, tzname → the name or "UTC±HH:MM[:SS[.ffffff]]"

FAQ

dt.utcoffset() returns a timedelta (None if naive). For hours: dt.utcoffset().total_seconds() / 3600; for text: dt.strftime("%z") or "%:z".