Time Zones with zoneinfo
Work with aware datetimes.
Time Zones with zoneinfo is a free Python Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Python Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Naive vs aware datetimes
A naive datetime has no timezone info — it just says '2 PM' with no clue which 2 PM. An aware datetime carries a timezone, so it pins down an exact moment worldwide.
Aware datetimes prevent bugs when users span multiple regions.
from datetime import datetime
naive = datetime(2026, 5, 30, 14, 0)
print(naive.tzinfo)Importing zoneinfo
Python 3.9+ ships zoneinfo in the standard library. Import ZoneInfo and pass an IANA timezone name like 'Europe/Istanbul' or 'America/New_York'.
from zoneinfo import ZoneInfo
tz = ZoneInfo('Europe/Istanbul')
print(tz)Creating an aware datetime
Pass tzinfo=ZoneInfo(...) when constructing a datetime to make it aware. Now it knows exactly which region it belongs to.
from datetime import datetime
from zoneinfo import ZoneInfo
d = datetime(2026, 5, 30, 14, 0, tzinfo=ZoneInfo('Europe/Istanbul'))
print(d)
print(d.tzinfo)UTC as the anchor
UTC is the universal reference. Use datetime.now(ZoneInfo('UTC')) to get the current aware UTC time. Storing times in UTC is best practice.
from datetime import datetime
from zoneinfo import ZoneInfo
utc_now = datetime(2026, 5, 30, 11, 0, tzinfo=ZoneInfo('UTC'))
print(utc_now)Converting between zones
.astimezone(tz) converts an aware datetime to another timezone, adjusting the clock so it still names the same instant.
from datetime import datetime
from zoneinfo import ZoneInfo
utc = datetime(2026, 5, 30, 11, 0, tzinfo=ZoneInfo('UTC'))
ist = utc.astimezone(ZoneInfo('Europe/Istanbul'))
print('UTC:', utc)
print('Istanbul:', ist)Same instant, different clocks
After conversion the wall-clock numbers differ but the underlying instant is identical. Comparing two aware datetimes compares the real moments, not the displayed digits.
from datetime import datetime
from zoneinfo import ZoneInfo
utc = datetime(2026, 5, 30, 11, 0, tzinfo=ZoneInfo('UTC'))
ny = utc.astimezone(ZoneInfo('America/New_York'))
print(utc == ny)Reading the UTC offset
The .utcoffset() method returns a timedelta showing how far the zone is from UTC at that moment — including any daylight saving adjustment.
from datetime import datetime
from zoneinfo import ZoneInfo
d = datetime(2026, 5, 30, 14, 0, tzinfo=ZoneInfo('Europe/Istanbul'))
print('Offset:', d.utcoffset())Daylight saving handled for you
zoneinfo uses the system timezone database, so it knows when daylight saving starts and ends. The same zone can have different offsets across the year.
from datetime import datetime
from zoneinfo import ZoneInfo
winter = datetime(2026, 1, 15, 12, 0, tzinfo=ZoneInfo('America/New_York'))
summer = datetime(2026, 7, 15, 12, 0, tzinfo=ZoneInfo('America/New_York'))
print('Winter:', winter.utcoffset())
print('Summer:', summer.utcoffset())Attaching a zone to a naive time
If a naive datetime represents a known local time, attach a zone with .replace(tzinfo=...). This labels it without shifting the clock.
from datetime import datetime
from zoneinfo import ZoneInfo
naive = datetime(2026, 5, 30, 9, 0)
aware = naive.replace(tzinfo=ZoneInfo('Europe/Istanbul'))
print(aware)Avoid mixing naive and aware
You cannot subtract or compare a naive datetime with an aware one — Python raises a TypeError. Keep your datetimes consistent throughout a program.
from datetime import datetime
from zoneinfo import ZoneInfo
naive = datetime(2026, 5, 30, 9, 0)
aware = datetime(2026, 5, 30, 9, 0, tzinfo=ZoneInfo('UTC'))
try:
print(aware - naive)
except TypeError as e:
print('Error:', e)Formatting with the zone
The %Z code prints the timezone name and %z prints the numeric offset when you format an aware datetime.
from datetime import datetime
from zoneinfo import ZoneInfo
d = datetime(2026, 5, 30, 14, 0, tzinfo=ZoneInfo('Europe/Istanbul'))
print(d.strftime('%Y-%m-%d %H:%M %Z %z'))Quick Check
What is the key difference between a naive and an aware datetime?
Recap: Time Zones with zoneinfo
Summary:
- Naive datetimes lack timezone info; aware ones carry
tzinfo. - Use
ZoneInfo('Region/City')from thezoneinfomodule. .astimezone()converts an aware datetime to another zone.zoneinfohandles daylight saving automatically, and you should never mix naive with aware datetimes.
from datetime import datetime
from zoneinfo import ZoneInfo
utc = datetime(2026, 5, 30, 12, 0, tzinfo=ZoneInfo('UTC'))
print(utc.astimezone(ZoneInfo('Europe/Istanbul')))Frequently asked questions
Is the “Time Zones with zoneinfo” lesson free?
Yes — the full text of “Time Zones with zoneinfo” is free to read here on the web, and the Python Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Python Academy course, upgrade to CoddyKit PRO.
What will I learn in “Time Zones with zoneinfo”?
Work with aware datetimes. You practise Python Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Python Academy?
No prior experience is required. Python Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Time Zones with zoneinfo” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Python Academy lesson?
Yes. Every Python Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- date, time, datetime
- Timedelta and Arithmetic
- Formatting and Parsing
- Time Zones with zoneinfo