FObersteiner
FObersteiner

Reputation: 25564

Get local time zone name on Windows (Python 3.9 zoneinfo)

Checking out the zoneinfo module in Python 3.9, I was wondering if it also offers a convenient option to retrieve the local time zone (OS setting) on Windows.

On GNU/Linux, you can do

from datetime import datetime
from zoneinfo import ZoneInfo

naive = datetime(2020, 6, 11, 12)
aware = naive.replace(tzinfo=ZoneInfo('localtime'))

but on Windows, that throws

ZoneInfoNotFoundError: 'No time zone found with key localtime'

so would I still have to use a third-party library? e.g.

import time
import dateutil

tzloc = dateutil.tz.gettz(time.tzname[time.daylight])
aware = naive.replace(tzinfo=tzloc)

Since time.tzname[time.daylight] returns a localized name (German in my case, e.g. 'Mitteleuropäische Sommerzeit'), this doesn't work either:

aware = naive.replace(tzinfo=ZoneInfo(tzloc))

Any thoughts?


p.s. to try this on Python < 3.9, use backports (see also this answer):

pip install backports.zoneinfo
pip install tzdata # needed on Windows

Upvotes: 12

Views: 16196

Answers (3)

FObersteiner
FObersteiner

Reputation: 25564

While astimezone(None) is convenient, sometimes you might want to get the IANA name of the time zone your OS is configured to use. Be careful though, Windows does not use the IANA database; a mapping is required from "Windows time zone" to IANA identifier. That mapping might be wrong, see Philip Couling's answer below.

Version 4 of tzlocal will also use zoneinfo for that whilst maintaining compatibility with pytz through the deprecation shim:

>>> import tzlocal
>>> print(tzlocal.get_localzone())
Europe/Berlin
>>> print(repr(tzlocal.get_localzone()))
_PytzShimTimezone(zoneinfo.ZoneInfo(key='Europe/Berlin'), 'Europe/Berlin')

[update] With version 5, the pytz deprecation shim is removed, see also tzlocal's readme:

>>> print(tzlocal.get_localzone())
Europe/Berlin
>>> print(repr(tzlocal.get_localzone()))
zoneinfo.ZoneInfo(key='Europe/Berlin')

Upvotes: 6

Philip Couling
Philip Couling

Reputation: 14903

The question is founded on a minunderstanding of timezones

That's understandable; the topic is maddeningly complex, even for such trivially simple questions!

The misunderstanding here is to believe zoneinfo can be related to MS Window's local timezones. It can't! They are two completely different things, even if they look alike:

  • zoneinfo Is for IANA timezones
  • MS Windows does not use IANA timezones

Jon Skeet discusses it here: IANA to Windows timezone mapping. The problem is not just about the names of the timezones, but their actual meaning.

What is a timezone?

Timezones don't really exist. The more you try to prove they exist, the more you find they really really don't exist.

Some humans observe different time on the clock to other humans. There have been attempts to catalogue which humans observe which times and how these all fit together. But these are political decisions and sometimes politics gets very messy.

When you try to catalog which humans observe which timezone, you will find cases were there is no right answer. Eg: Lebinon in 2023.

But I found a way to map them...

The main problem is that IANA (used by zoneinfo) is a seperate database to the one used by MS Windows. While you can find many mappings between the two they don't necessarily coordinate with each other and so can really disagree on offsets.

Really dangerously you can find mappings that look like they match but suddenly and unexpectly disagree, so unless you are going to very carefully handle the conversion yourself, you shouldn't try to get the IANA name for an MS Windows configured timezone.

Upvotes: 5

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241573

You don't need to use zoneinfo to use the system local time zone. You can simply pass None (or omit) the time zone when calling datetime.astimezone.

From the docs:

If called without arguments (or with tz=None) the system local timezone is assumed. The .tzinfo attribute of the converted datetime instance will be set to an instance of timezone with the zone name and offset obtained from the OS.

Thus:

from datetime import datetime

naive = datetime(2020, 6, 11, 12)
aware = naive.astimezone()

Upvotes: 10

Related Questions