0Pricing
Python Academy · Lesson

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 the zoneinfo module.
  • .astimezone() converts an aware datetime to another zone.
  • zoneinfo handles 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

  1. date, time, datetime
  2. Timedelta and Arithmetic
  3. Formatting and Parsing
  4. Time Zones with zoneinfo
← Back to Python Academy