Offset tetap +07:00 dari Chapter Timezone-Aware datetime cukup untuk WIB, tetapi dunia menyimpan ratusan zona dengan aturan berbeda — sebagian bahkan menggeser jam dua kali setahun lewat daylight saving time (DST). Standar industri untuk menamai zona adalah database IANA, misalnya Asia/Jakarta atau Europe/London. Module zoneinfo (hadir sejak Python 3.9) memberi kita akses langsung ke database tersebut. Chapter ini membahas pemakaiannya, perilakunya saat DST berganti, dan cara menjelajahi daftar zona yang tersedia.

Nama Zona IANA #

Class ZoneInfo membaca definisi zona dari sistem operasi (Linux dan macOS) berdasarkan nama IANA, lalu menyimpannya dalam cache sehingga nama yang sama dipakai berulang kali tidak memicu pembacaan ulang:

python
from datetime import datetime
from zoneinfo import ZoneInfo

jakarta = ZoneInfo("Asia/Jakarta")
rapat = datetime(2025, 6, 15, 10, 30, tzinfo=jakarta)

print(rapat.isoformat())
print(rapat.utcoffset())

Output yang Dihasilkan:

text
2025-06-15T10:30:00+07:00
7:00:00

Mari kita telaah apa yang terjadi pada baris-baris kode di atas:

  1. Baris 4 (jakarta = ZoneInfo("Asia/Jakarta")): membuat object ZoneInfo bernama jakarta dengan membaca definisi zona Asia/Jakarta dari database IANA.
  2. Baris 5 (datetime(..., tzinfo=jakarta)): object yang sama dipakai sebagai tzinfo, sehingga rapat menjadi object aware bergaya Chapter Timezone-Aware datetime.
  3. Baris 8 (utcoffset()): menanyakan offset yang berlaku pada tanggal 15 Juni 2025 menurut definisi zona — jawabannya 7:00:00.

Kode ini serupa dengan versi timezone(timedelta(hours=7)) di Chapter sebelumnya, tetapi kini zona punya nama resmi yang terdokumentasi — jauh lebih ekspresif daripada angka offset. Class ZoneInfo juga melengkapi datetime.now() agar menghasilkan object aware:

python
from datetime import datetime
from zoneinfo import ZoneInfo

sekarang_jakarta = datetime.now(tz=ZoneInfo("Asia/Jakarta"))

print(type(sekarang_jakarta).__name__)
print(sekarang_jakarta.tzinfo)
print(sekarang_jakarta.utcoffset())

Output yang Dihasilkan:

text
datetime
Asia/Jakarta
7:00:00

Nilai jam pada sekarang_jakarta berubah setiap eksekusi mengikuti waktu nyata, tetapi tiga baris di atas sengaja hanya mencetak hal yang stabil: tipe object, nama zona yang menempel, dan offsetnya. Indonesia membentang tiga zona berdasarkan Peraturan Pemerintah No. 41 Tahun 1987:

python
from datetime import datetime
from zoneinfo import ZoneInfo

for nama_zona in ["Asia/Jakarta", "Asia/Pontianak", "Asia/Makassar", "Asia/Jayapura"]:
    zona = ZoneInfo(nama_zona)
    offset = datetime(2025, 6, 15, tzinfo=zona).utcoffset()
    print(f"{nama_zona}: {offset}")

Output yang Dihasilkan:

text
Asia/Jakarta: 7:00:00
Asia/Pontianak: 7:00:00
Asia/Makassar: 8:00:00
Asia/Jayapura: 9:00:00
Nama zona IANAOffsetWilayah umum
Asia/Jakarta, Asia/PontianakUTC+7WIB
Asia/MakassarUTC+8WITA
Asia/JayapuraUTC+9WIT

Daylight Saving Time dalam Praktik #

Sebagian wilayah di belahan bumi utara memajukan jam satu kali penuh menjelang musim panas dan mengembalikannya menjelang musim dingin. Akibatnya, offset satu zona berubah-ubah menurut tanggal — hal yang tidak bisa diungkap offset tetap. Saat jam dikembalikan (fall back), satu jam dinding terjadi dua kali:

python
from datetime import datetime, timezone
from zoneinfo import ZoneInfo

new_york = ZoneInfo("America/New_York")

sebelum = datetime(2024, 11, 3, 5, 0, tzinfo=timezone.utc).astimezone(new_york)
sesudah = datetime(2024, 11, 3, 6, 0, tzinfo=timezone.utc).astimezone(new_york)

print(sebelum.isoformat())
print(sesudah.isoformat())

Output yang Dihasilkan:

text
2024-11-03T01:00:00-04:00
2024-11-03T01:00:00-05:00

Dua momen UTC yang berbeda satu jam (05:00 dan 06:00 UTC) keduanya tampil sebagai pukul 01:00 di New York — sekali dengan offset -04:00 (masih EDT), sekali dengan -05:00 (sudah EST). Pukul 01:00 benar-benar terjadi dua kali pada tanggal itu. Sebaliknya, saat jam dimajukan (spring forward), satu jam dinding dilompati dan tidak pernah terjadi:

python
from datetime import datetime, timezone
from zoneinfo import ZoneInfo

amsterdam = ZoneInfo("Europe/Amsterdam")

pagi = datetime(2025, 3, 30, 0, 30, tzinfo=timezone.utc).astimezone(amsterdam)
siang = datetime(2025, 3, 30, 1, 30, tzinfo=timezone.utc).astimezone(amsterdam)

print(pagi.isoformat())
print(siang.isoformat())
print(siang.timestamp() - pagi.timestamp())

Output yang Dihasilkan:

text
2025-03-30T01:30:00+01:00
2025-03-30T03:30:00+02:00
3600.0

Kedua momen nyatanya hanya terpisah satu jam — dibuktikan selisih timestamp() sebesar 3600.0 detik — tetapi jam dinding Amsterdam melompat dari 01:30 langsung ke 03:30, karena pukul 02:30 tidak pernah ada pada 30 Maret 2025. Perhatikan juga bahwa pagi memakai offset +01:00 sedangkan siang memakai +02:00: method astimezone() menghitung offset yang benar untuk setiap tanggal secara otomatis, persis alasan module ini unggul dibanding offset tetap.

Menjelajahi Zona yang Tersedia #

Function available_timezones() mengembalikan set berisi seluruh nama zona yang dikenali sistem. Karena berupa set, urutannya acak — baca dengan sorted() bila butuh hasil yang stabil:

python
from zoneinfo import available_timezones

zona_indonesia = sorted(
    zona for zona in available_timezones()
    if zona.split("/")[-1] in {"Jakarta", "Makassar", "Pontianak", "Jayapura"}
)
print(zona_indonesia)

Output yang Dihasilkan:

text
['Asia/Jakarta', 'Asia/Jayapura', 'Asia/Makassar', 'Asia/Pontianak']

Daftar lengkapnya berisi ratusan zona dan berubah antar versi database, jadi jangan menghard-code jumlahnya. Nama zona berformat Area/Lokasi seperti Asia/Makassar atau America/New_York.

Konversi Berantai Antar Kota #

Menggabungkan ZoneInfo dan astimezone(), satu momen rapat dapat ditampilkan untuk banyak kota sekaligus:

python
from datetime import datetime
from zoneinfo import ZoneInfo

rapat = datetime(2025, 6, 15, 10, 30, tzinfo=ZoneInfo("Asia/Jakarta"))

for nama_zona in ["Asia/Makassar", "Asia/Jayapura", "Europe/London"]:
    lokal = rapat.astimezone(ZoneInfo(nama_zona))
    print(nama_zona, "->", lokal.strftime("%H:%M"))

Output yang Dihasilkan:

text
Asia/Makassar -> 11:30
Asia/Jayapura -> 12:30
Europe/London -> 04:30

Satu momen absolut menghasilkan empat tampilan berbeda: 10:30 di Jakarta, 11:30 di Makassar, 12:30 di Jayapura, dan 04:30 di London. Cara strftime() menghasilkan angka-angka tersebut adalah topik Chapter Parsing dan Formatting datetime — dan untuk menampilkannya dalam Bahasa Indonesia, lanjutkan ke Chapter Locale dan Formatting.