datetime.timezone

The built-in tzinfo for fixed offsets. It knows nothing about daylight saving: +01:00 is +01:00 all year. For real regional zones (Europe/Paris) use the separate zoneinfo module.

datetime classPython 3.2+Live demo
Common call
timezone(timedelta(hours=-5))
Returns
datetime.timezone(datetime.timedelta(days=-1, seconds=68400))
Replaces
pytz.FixedOffset and hand-written tzinfo subclasses for offsets
Watch out
Fixed: no DST. Offsets must be strictly within ±24 h
timezone(offsetoffset — The UTC offset, strictly between -timedelta(hours=24) and timedelta(hours=24). Seconds and microseconds are allowed (3.7+).type: timedelta · required, namename — What tzname() and %Z return. Without it the name is generated: 'UTC+05:30', or 'UTC' for a zero offset.type: str · default: None=None)
→ timezone

Demo

Live evaluation
An offset in hours and minutes. repr() shows the normalized timedelta, str() the generated name.
Try:
Inputs
hoursinthours
minutesintminutes
Code
from datetime import timedelta, timezone
tz = timezone(timedelta(hours=5, minutes=30))
(tz, str(tz))
Result
(datetime.timezone(datetime.timedelta(seconds=19800)), 'UTC+05:30')

A zero offset with no name gives back the timezone.utc singleton, so its repr is datetime.timezone.utc. Converting keeps the instant: 23:00 UTC shown at -07:00 is 16:00 the same day, at +09:00 it would already be the next day. The name is a free-form label — timezone(timedelta(hours=3), "PST") is accepted and compares equal to any other +03:00.

Parameters

NameTypeRequiredDescription
offsettimedeltayesThe UTC offset, strictly between -timedelta(hours=24) and timedelta(hours=24). Seconds and microseconds are allowed (3.7+).
namestrno (None)What tzname() and %Z return. Without it the name is generated: 'UTC+05:30', or 'UTC' for a zero offset.

Return value

timezone — A tzinfo whose utcoffset() is always `offset` and whose dst() is always None.

Common patterns

Parse, then show in a fixed offset
Aware input converts directly with astimezone.
from datetime import datetime, timedelta, timezone
ist = timezone(timedelta(hours=5, minutes=30), 'IST')
local = datetime.fromisoformat('2026-09-29T12:00Z').astimezone(ist)
Real zones with DST
zoneinfo (Python 3.9+) gives a tzinfo that knows each region's rules.
from datetime import datetime
from zoneinfo import ZoneInfo
paris = datetime(2026, 7, 1, 12, tzinfo=ZoneInfo('Europe/Paris'))
Offset from an integer of minutes
e.g. a browser getTimezoneOffset() value (note its sign is inverted).
from datetime import timedelta, timezone
tz = timezone(timedelta(minutes=-js_offset_minutes))

Examples

1. A fixed offset
from datetime import timedelta, timezone timezone(timedelta(hours=5, minutes=30))
Returns
datetime.timezone(datetime.timedelta(seconds=19800))
2. Negative offsets use days=-1
from datetime import timedelta, timezone tz = timezone(timedelta(hours=-5)) (tz, str(tz))
Returns
(datetime.timezone(datetime.timedelta(days=-1, seconds=68400)), 'UTC-05:00')
3. A zero offset IS timezone.utc
from datetime import timedelta, timezone timezone(timedelta(0)) is timezone.utc
Returns
True
4. Convert with astimezone
from datetime import datetime, timedelta, timezone, UTC ist = timezone(timedelta(hours=5, minutes=30), 'IST') datetime(2026, 9, 29, 12, tzinfo=UTC).astimezone(ist)
Returns
datetime.datetime(2026, 9, 29, 17, 30, tzinfo=datetime.timezone(datetime.timedelta(seconds=19800), 'IST'))
5. The name feeds %Z
from datetime import datetime, timedelta, timezone ist = timezone(timedelta(hours=5, minutes=30), 'IST') datetime(2026, 9, 29, 12, tzinfo=ist).strftime('%H:%M %Z %z')
Returns
'12:00 IST +0530'
6. Equality ignores the name
from datetime import timedelta, timezone timezone(timedelta(hours=1)) == timezone(timedelta(hours=1), 'CET')
Returns
True
7. No DST — dst() is None
from datetime import timedelta, timezone timezone(timedelta(hours=2)).dst(None) is None
Returns
True
8. Cannot be subclassed
from datetime import timezone class MyZone(timezone): pass
Returns
TypeError: type 'datetime.timezone' is not an acceptable base type

Pitfalls

1. An int instead of a timedelta
The offset must be a timedelta, not hours as a number.
timezone(-5)
from datetime import timezone
timezone(-5)
TypeError: timezone() argument 1 must be datetime.timedelta, not int
timedelta(hours=-5)
from datetime import timedelta, timezone
timezone(timedelta(hours=-5))
datetime.timezone(datetime.timedelta(days=-1, seconds=68400))
2. Using a fixed offset for a region with DST
Paris is +01:00 in winter and +02:00 in summer. A timezone(timedelta(hours=1)) is wrong for half the year — the zoneinfo module knows the rules.
fixed +01:00 in July
from datetime import datetime, timedelta, timezone
datetime(2026, 7, 1, 12, tzinfo=timezone(timedelta(hours=1))).isoformat()
'2026-07-01T12:00:00+01:00'
the summer offset
from datetime import datetime, timedelta, timezone
datetime(2026, 7, 1, 12, tzinfo=timezone(timedelta(hours=2))).isoformat()
'2026-07-01T12:00:00+02:00'
3. Offsets of a day or more
Real offsets run from -12:00 to +14:00; the class allows anything strictly inside ±24 hours.
24 hours
from datetime import timedelta, timezone
timezone(timedelta(hours=24))
ValueError: offset must be a timedelta strictly between -timedelta(hours=24) and timedelta(hours=24), not datetime.timedelta(days=1).
within range
from datetime import timedelta, timezone
timezone(timedelta(hours=14))
datetime.timezone(datetime.timedelta(seconds=50400))

When to use

Use it
  • UTC (timezone.utc or its alias UTC) — the right tzinfo for stored timestamps
  • Offsets that really are fixed: parsed from ISO text, from an API, or a fixed business rule
Reach for something else
  • Regions with daylight saving time → zoneinfo.ZoneInfo("Europe/Paris")
  • Custom rules → subclass tzinfo (timezone itself cannot be subclassed)

Notes

CPython impl
PyDateTime_TimeZone in Modules/_datetimemodule.c; timezone(timedelta(0)) without a name returns the timezone.utc singleton
Range
timezone.min is -23:59 and timezone.max is +23:59; the constructor accepts anything strictly inside ±24 hours
Methods
utcoffset(dt) → offset, dst(dt) → None, tzname(dt) → name or generated UTC±HH:MM, fromutc(dt) → dt + offset
Equality
Two timezone objects are equal when their offsets are equal; the name is ignored

FAQ

timezone(timedelta(hours=5, minutes=30)) for +05:30, timezone(timedelta(hours=-5)) for -05:00, and timezone.utc (or UTC on 3.11+) for zero. Pass it as tzinfo= when building a datetime, or to astimezone() to convert.