Skip to content
Flying Animal

Simple IANA Time Zone Abbreviations for Python

🕒 Published at:

Introduction

If you’ve ever needed to show a friendly time zone abbreviation like SGT or EDT from an IANA zone name (e.g., Asia/Singapore, America/New_York), you’ve probably discovered it’s trickier than it should be. Python’s excellent zoneinfo handles time conversions, but it doesn’t give you a simple, static lookup for abbreviations.

Meet tznn — a tiny helper that maps IANA time zones to their common abbreviations with a single import.

Features:

  • Need a quick SGT/EDT abbreviation from an IANA zone? Use tznn.
  • Tiny, dependency-light, works cross-platform.
  • Install: pip install tznn

Why this exists

A lot of apps need to display short, human-friendly zone labels alongside times (SGT, EDT, CET…), but:

  • The standard library focuses on accurate conversions and offsets, not static abbreviations.
  • Abbreviations can vary with DST and history; sometimes you just want a stable label for UI or configuration.

tznn provides a straightforward answer: a packaged JSON mapping from IANA zone names to common abbreviations.

Let's look at simple code from default python, problem stament, I want to get TimeZone code at New York and Singapore

python
from datetime import datetime
from zoneinfo import ZoneInfo
dt_utc = datetime(2025, 9, 23, 3, 2, 7, tzinfo=ZoneInfo("UTC"))
dt_ny = dt_utc.astimezone(ZoneInfo("America/New_York"))
dt_sg = dt_utc.astimezone(ZoneInfo("Asia/Singapore"))
print(dt_ny.strftime("%d/%m/%Y %H:%M:%S %Z %z"))  # → 22/09/2025 23:02:07 EDT -0400
print(dt_sg.strftime("%d/%m/%Y %H:%M:%S %Z %z"))  # → 23/09/2025 11:02:07 +08 +0800

In .NET, you can try using NodaTime.

csharp
using NodaTime;
using NodaTime.Text;
// UTC instant
var instant = Instant.FromUtc(2025, 9, 23, 3, 2, 7);

var nyZone = DateTimeZoneProviders.Tzdb["America/New_York"];
var sgZone = DateTimeZoneProviders.Tzdb["Asia/Singapore"];

var nyTime = instant.InZone(nyZone);
var sgTime = instant.InZone(sgZone);
// Use NodaTime's offset pattern
Console.WriteLine($"{nyTime:dd/MM/yyyy HH:mm:ss} {nyTime.Offset}");
Console.WriteLine($"{sgTime:dd/MM/yyyy HH:mm:ss} {sgTime.Offset}");

// If you also want the zone ID
Console.WriteLine($"{nyTime:dd/MM/yyyy HH:mm:ss} {nyTime.Zone.Id} {nyTime.Offset}");
Console.WriteLine($"{sgTime:dd/MM/yyyy HH:mm:ss} {sgTime.Zone.Id} {sgTime.Offset}");

The expected output for Singapore is SGT, but it returns ?????? instead. This is because zoneinfo does not include static abbreviations.

When I look into the details at zoneinfo doc, and try to decompress the IANA time zone database, I founded some interesting things:

  • Becasue the history of time zones is complex and changes over time, the same location may have different abbreviations at different times (e.g., EST vs. EDT for New York).

Example : Viet Name using GMT+7, but the abbreviation is ICT, but we are using location Asia/Ho_Chi_Minh match with GMT+7 for the same time zone with Russia; Indochina; Christmas Island

The code details from timezone source code )

text
# +07
XX	+1345+10031	Asia/Bangkok	Russia; Indochina; Christmas Island
  • The zoneinfo module focuses on accurate time conversions and offsets, not on providing a static mapping of abbreviations. That means it doesn't include a simple way to look up abbreviations for display purposes, and replaces them with numeric offsets like +0800.

What tznn does ?

  • List available IANA time zones
  • Look up the abbreviation (e.g., SGT, EDT) for a zone name
  • Return the entire zone → abbreviation mapping

It’s intentionally simple and fast. Abbreviations are static values from timezone.json—they’re not date-aware.

Install

Online via PyPI:

powershell
pip install tznn

Upgrade:

powershell
pip install -U tznn

From source:

powershell
pip install .
pip install -r requirements.txt

Note: On Windows, tzdata may be installed automatically if needed.

Quick start

python
from tznn import tznn

tz = tznn()

# 1) Get a sorted list of available IANA time zone names
zones = tz.get_available_time_zones()
print(len(zones), zones[:5])

# 2) Get the abbreviation for a known time zone
print(tz.get_abbr("Asia/Singapore"))      # -> "SGT"
print(tz.get_abbr("Asia/Ho_Chi_Minh"))    # -> "ICT"
print(tz.get_abbr("America/New_York"))    # -> e.g., "EDT"

# 3) Get the full mapping of zone -> abbreviation
mapping = tz.get_all_available_time_zones()
print(mapping["America/New_York"])        # -> "EDT"

A note on zoneinfo

zoneinfo is perfect for conversions and offsets, but it’s not a direct answer for static abbreviations. For example:

python
from datetime import datetime
from zoneinfo import ZoneInfo

dt_utc = datetime(2025, 9, 23, 3, 2, 7, tzinfo=ZoneInfo("UTC"))
dt_vn = dt_utc.astimezone(ZoneInfo("Asia/Ho_Chi_Minh"))
print(dt_vn.strftime("%d/%m/%Y %H:%M:%S %Z %z"))  # → 23/09/2025 10:02:07 ICT +0700

tznn complements this by giving you a fast, static label when you just need to display an abbreviation.

API in 30 seconds

  • get_available_time_zones() -> list[str]
    • Sorted list of IANA zone names in the data file.
  • get_all_available_time_zones() -> dict[str, str]
    • Entire mapping zone_name -> abbreviation.
  • get_abbr(tz_name: str) -> str
    • Abbreviation for a given zone name.
    • Raises ValueError if the zone doesn’t exist in the mapping.

Limitations

  • Abbreviations are static and don’t reflect historical or future DST changes.
  • If you need date-aware correctness, combine this with the standard library zoneinfo for conversions and offsets.

Quality and releases

  • CI runs on multiple Python versions (3.9–3.12).
  • Publishing is automated via GitHub Actions on release.
  • MIT licensed.

Knowledge

Interested with history from zoneinfo --- IGNORE ---

I seen some interesting things in message from source code, the war in Viet Nam make the time zone change a lot, and the details are not clear

bash
# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
		#STDOFF	7:06:30.13
Zone Asia/Ho_Chi_Minh	7:06:30 -	LMT	1906 Jul  1
			7:06:30	-	PLMT	1911 May  1 # Phù Liễn MT
			7:00	-	%z	1942 Dec 31 23:00
			8:00	-	%z	1945 Mar 14 23:00
			9:00	-	%z	1945 Sep  1 24:00
			7:00	-	%z	1947 Apr  1
			8:00	-	%z	1955 Jul  1 01:00
			7:00	-	%z	1959 Dec 31 23:00
			8:00	-	%z	1975 Jun 13
			7:00	-	%z

# From Paul Eggert (2019-02-19):
#
# The Ho Chi Minh entry suffices for most purposes as it agrees with all of
# Vietnam since 1975-06-13.  Presumably clocks often changed in south Vietnam
# in the early 1970s as locations changed hands during the war; however the
# details are unknown and would likely be too voluminous for this database.
#
# For timestamps in north Vietnam back to 1970 (the tzdb cutoff),
# use Asia/Bangkok; see the VN entries in the file zone1970.tab.
# For timestamps before 1970, see Asia/Hanoi in the file 'backzone'.

And so many backward in source code give me learning a lot about the history base on time zone and country changed

bash
# Alternate names for the same location

# Link	TARGET			LINK-NAME	#= TARGET1
Link	Africa/Nairobi		Africa/Asmera	#= Africa/Asmara
Link	America/Nuuk		America/Godthab
Link	Asia/Ashgabat		Asia/Ashkhabad
Link	Asia/Kolkata		Asia/Calcutta
Link	Asia/Shanghai		Asia/Chungking	#= Asia/Chongqing
Link	Asia/Dhaka		Asia/Dacca
# Istanbul is in both continents.
Link	Europe/Istanbul		Asia/Istanbul
Link	Asia/Kathmandu		Asia/Katmandu
Link	Asia/Macau		Asia/Macao
Link	Asia/Yangon		Asia/Rangoon
Link	Asia/Ho_Chi_Minh	Asia/Saigon
Link	Asia/Thimphu		Asia/Thimbu
Link	Asia/Makassar		Asia/Ujung_Pandang
Link	Asia/Ulaanbaatar	Asia/Ulan_Bator
Link	Atlantic/Faroe		Atlantic/Faeroe
Link	Europe/Kyiv		Europe/Kiev
# Classically, Cyprus is in Asia; e.g. see Herodotus, Histories, I.72.
# However, for various reasons many users expect to find it under Europe.
Link	Asia/Nicosia		Europe/Nicosia
Link	Pacific/Honolulu	HST
Link	America/Los_Angeles	PST8PDT
Link	Pacific/Guadalcanal	Pacific/Ponape	#= Pacific/Pohnpei
Link	Pacific/Port_Moresby	Pacific/Truk	#= Pacific/Chuuk